00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <errno.h>
00026 #include <sys/ioctl.h>
00027 #include <signal.h>
00028 #include <pthread.h>
00029 #include <semaphore.h>
00030 #include <time.h>
00031 #include <assert.h>
00032
00033 #include <adjust.h>
00034 #include <mostdef1.h>
00035 #include <mostns1.h>
00036 #include <mostnetsdll.h>
00037 #include <par_cp.h>
00038
00039 #include "global.h"
00040 #include "most-netservice.h"
00041 #include "service.h"
00042
00043 static pthread_t service_thread_descriptor;
00044 static sigset_t old_sigset;
00045 static sem_t startup_sem;
00046 static sem_t thread_sem;
00047
00048
00049 static unsigned int events_mns = 0;
00050
00051
00052 void MostStartUpFinished(void)
00053 {
00054
00055 sem_post(&startup_sem);
00056 }
00057
00058
00059 void *service_thread_func(void *cookie)
00060 {
00061 int ret;
00062 sigset_t sig;
00063 struct timespec next_timeout = { 0, 0 };
00064 siginfo_t sinfo;
00065 long long last_time, cur_time, time_diff;
00066 int tmp;
00067 int most_service = 0;
00068
00069 PRINT_TRACE();
00070
00071
00072 sigemptyset(&sig);
00073 sigaddset(&sig, MOST_RT_SIGNAL);
00074 sigaddset(&sig, MOST_RT_SIGNAL_TIMER);
00075
00076
00077 sem_post(&thread_sem);
00078
00079 PRINT_TRACE("Waiting until MostStartUp has been called");
00080
00081
00082 sem_wait(&startup_sem);
00083
00084 TIME_IN_MS(last_time);
00085
00086 for (;;) {
00087 PRINT_TRACE("Waiting for a signal, timeout = { %ld, %ld }", next_timeout.tv_sec,
00088 next_timeout.tv_nsec);
00089
00090
00091 ret = sigtimedwait(&sig, &sinfo, &next_timeout);
00092 if (ret == -1 && errno != EAGAIN) {
00093 PERR_DEBUG("sigtimedwait error");
00094 continue;
00095 }
00096
00097 PRINT_TRACE("Signal received, ret = %d, value = %d", ret, sinfo.si_value.sival_int);
00098
00099
00100
00101
00102 TIME_IN_MS(cur_time);
00103 time_diff = cur_time - last_time;
00104 last_time = cur_time;
00105
00106 PRINT_TRACE("time_diff = %lld", time_diff);
00107 assert(time_diff >= 0);
00108
00109 MostTimerIntDiff( (word)time_diff );
00110
00111
00112 tmp = MostGetMinTimeout();
00113 if (tmp == 0xffff) {
00114
00115 next_timeout.tv_sec = 1;
00116 next_timeout.tv_nsec = 0;
00117 } else {
00118 next_timeout.tv_sec = tmp / 1000;
00119 tmp %= 1000;
00120 next_timeout.tv_nsec = tmp * 1000 * 1000;
00121 }
00122
00123
00124 if (next_timeout.tv_sec > 0) {
00125 next_timeout.tv_sec = 1;
00126 next_timeout.tv_nsec = 0;
00127 }
00128
00129
00130 if (ret == -1 && !most_service) {
00131 continue;
00132 }
00133
00134
00135 events_mns = 0;
00136
00137
00138 if (ret == MOST_RT_SIGNAL && sinfo.si_value.sival_int == MNS_INT) {
00139 events_mns |= MNS_E_INT | MNS_E_REQ;
00140 }
00141
00142
00143 if (ret == MOST_RT_SIGNAL_TIMER) {
00144 events_mns |= MNS_E_TIMER;
00145 }
00146
00147
00148 if (most_service > 0) {
00149 events_mns |= MNS_E_PEN;
00150 }
00151
00152
00153 if (MostGetState() != NET_ON) {
00154 events_mns |= MNS_E_TIMER;
00155 }
00156
00157
00158 if (events_mns > 0) {
00159
00160
00161
00162
00163
00164 pthread_mutex_lock(&g_nets_mutex);
00165 most_service = MostService(0, events_mns);
00166 pthread_mutex_unlock(&g_nets_mutex);
00167 }
00168 }
00169 }
00170
00171
00172 int service_thread_init(void)
00173 {
00174 int ret;
00175 sigset_t sig;
00176 struct interrupt_set_arg interrupt_set = {MOST_RT_SIGNAL, MNS_INT};
00177
00178 PRINT_TRACE();
00179
00180
00181 sem_init(&startup_sem, 0, 0);
00182 sem_init(&thread_sem, 0, 0);
00183
00184
00185 sigemptyset(&sig);
00186 sigaddset(&sig, MOST_RT_SIGNAL);
00187 sigaddset(&sig, MOST_RT_SIGNAL_TIMER);
00188
00189 ret = sigprocmask(SIG_BLOCK, &sig, &old_sigset);
00190 if (ret != 0) {
00191 PERR_DEBUG("Setting procmask failed");
00192 return E_SIGNAL;
00193 }
00194
00195
00196 ret = ioctl(g_control_fd, MOST_NETS_IRQ_SET, &interrupt_set);
00197 if (ret < 0) {
00198 PERR_DEBUG("Registering interrupts at the driver failed");
00199 ret = E_IOCTL;
00200 goto out_procmask;
00201 }
00202
00203
00204 ret = pthread_create(&service_thread_descriptor, NULL, service_thread_func, NULL);
00205 if (ret < 0) {
00206 PERR_DEBUG("Thread creation failed");
00207 ret = E_THREAD;
00208 goto out_ioctl;
00209 }
00210
00211
00212 sem_wait(&thread_sem);
00213
00214 return E_SUCCESS;
00215
00216 out_procmask:
00217 sigprocmask(SIG_SETMASK, &old_sigset, NULL);
00218 out_ioctl:
00219 interrupt_set.sigmask = 0;
00220 ioctl(g_control_fd, MOST_NETS_IRQ_SET, &interrupt_set);
00221 return ret;
00222 }
00223
00224
00225 void service_thread_finish(void)
00226 {
00227 struct interrupt_set_arg interrupt_set = {0, 0};
00228 int ret;
00229
00230
00231 ret = ioctl(g_control_fd, MOST_NETS_IRQ_SET, &interrupt_set);
00232 if (ret < 0) {
00233 PERR_DEBUG("Deregistering interrupts at the driver failed");
00234 }
00235
00236
00237 ret = pthread_cancel(service_thread_descriptor);
00238 if (ret != 0) {
00239 PERR_DEBUG("Cancelling service thread failed");
00240 }
00241
00242
00243 ret = sigprocmask(SIG_SETMASK, &old_sigset, NULL);
00244 if (ret != 0) {
00245 PERR_DEBUG("Restoring procmask failed");
00246 }
00247 }
00248
00249