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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include <stdio.h>
00048
00049 #include "sys/process.h"
00050 #include "sys/arg.h"
00051
00052
00053
00054
00055 struct process *process_list = NULL;
00056 struct process *process_current = NULL;
00057
00058 static process_event_t lastevent;
00059
00060
00061
00062
00063 struct event_data {
00064 process_event_t ev;
00065 process_data_t data;
00066 struct process *p;
00067 };
00068
00069 static process_num_events_t nevents, fevent;
00070 static struct event_data events[PROCESS_CONF_NUMEVENTS];
00071
00072 #if PROCESS_CONF_STATS
00073 process_num_events_t process_maxevents;
00074 #endif
00075
00076 static volatile unsigned char poll_requested;
00077
00078 #define PROCESS_STATE_NONE 0
00079 #define PROCESS_STATE_RUNNING 1
00080 #define PROCESS_STATE_CALLED 2
00081
00082 static void call_process(struct process *p, process_event_t ev, process_data_t data);
00083
00084 #define DEBUG 0
00085 #if DEBUG
00086 #include <stdio.h>
00087 #define PRINTF(...) printf(__VA_ARGS__)
00088 #else
00089 #define PRINTF(...)
00090 #endif
00091
00092
00093 process_event_t
00094 process_alloc_event(void)
00095 {
00096 return lastevent++;
00097 }
00098
00099 void
00100 process_start(struct process *p, const char *arg)
00101 {
00102 struct process *q;
00103
00104
00105
00106 for(q = process_list; q != p && q != NULL; q = q->next);
00107
00108
00109 if(q == p) {
00110 return;
00111 }
00112
00113 p->next = process_list;
00114 process_list = p;
00115 p->state = PROCESS_STATE_RUNNING;
00116 PT_INIT(&p->pt);
00117
00118 PRINTF("process: starting '%s'\n", PROCESS_NAME_STRING(p));
00119
00120
00121 process_post_synch(p, PROCESS_EVENT_INIT, (process_data_t)arg);
00122 }
00123
00124 static void
00125 exit_process(struct process *p, struct process *fromprocess)
00126 {
00127 register struct process *q;
00128 struct process *old_current = process_current;
00129
00130 PRINTF("process: exit_process '%s'\n", PROCESS_NAME_STRING(p));
00131
00132
00133
00134 for(q = process_list; q != p && q != NULL; q = q->next);
00135 if(q == NULL) {
00136 return;
00137 }
00138
00139 if(process_is_running(p)) {
00140
00141 p->state = PROCESS_STATE_NONE;
00142
00143
00144
00145
00146
00147
00148 for(q = process_list; q != NULL; q = q->next) {
00149 if(p != q) {
00150 call_process(q, PROCESS_EVENT_EXITED, (process_data_t)p);
00151 }
00152 }
00153
00154 if(p->thread != NULL && p != fromprocess) {
00155
00156 process_current = p;
00157 p->thread(&p->pt, PROCESS_EVENT_EXIT, NULL);
00158 }
00159 }
00160
00161 if(p == process_list) {
00162 process_list = process_list->next;
00163 } else {
00164 for(q = process_list; q != NULL; q = q->next) {
00165 if(q->next == p) {
00166 q->next = p->next;
00167 break;
00168 }
00169 }
00170 }
00171
00172 process_current = old_current;
00173 }
00174
00175 static void
00176 call_process(struct process *p, process_event_t ev, process_data_t data)
00177 {
00178 int ret;
00179
00180 #if DEBUG
00181 if(p->state == PROCESS_STATE_CALLED) {
00182 printf("process: process '%s' called again with event %d\n", PROCESS_NAME_STRING(p), ev);
00183 }
00184 #endif
00185
00186 if((p->state & PROCESS_STATE_RUNNING) &&
00187 p->thread != NULL) {
00188 PRINTF("process: calling process '%s' with event %d\n", PROCESS_NAME_STRING(p), ev);
00189 process_current = p;
00190 p->state = PROCESS_STATE_CALLED;
00191 ret = p->thread(&p->pt, ev, data);
00192 if(ret == PT_EXITED ||
00193 ret == PT_ENDED ||
00194 ev == PROCESS_EVENT_EXIT) {
00195 exit_process(p, p);
00196 } else {
00197 p->state = PROCESS_STATE_RUNNING;
00198 }
00199 }
00200 }
00201
00202 void
00203 process_exit(struct process *p)
00204 {
00205 exit_process(p, PROCESS_CURRENT());
00206 }
00207
00208 void
00209 process_init(void)
00210 {
00211 lastevent = PROCESS_EVENT_MAX;
00212
00213 nevents = fevent = 0;
00214 #if PROCESS_CONF_STATS
00215 process_maxevents = 0;
00216 #endif
00217
00218 process_current = process_list = NULL;
00219 }
00220
00221
00222
00223
00224
00225 static void
00226 do_poll(void)
00227 {
00228 struct process *p;
00229
00230 poll_requested = 0;
00231
00232 for(p = process_list; p != NULL; p = p->next) {
00233 if(p->needspoll) {
00234 p->state = PROCESS_STATE_RUNNING;
00235 p->needspoll = 0;
00236 call_process(p, PROCESS_EVENT_POLL, NULL);
00237 }
00238 }
00239 }
00240
00241
00242
00243
00244
00245
00246 static void
00247 do_event(void)
00248 {
00249 static process_event_t ev;
00250 static process_data_t data;
00251 static struct process *receiver;
00252 static struct process *p;
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 if(nevents > 0) {
00263
00264
00265 ev = events[fevent].ev;
00266
00267 data = events[fevent].data;
00268 receiver = events[fevent].p;
00269
00270
00271
00272 fevent = (fevent + 1) % PROCESS_CONF_NUMEVENTS;
00273 --nevents;
00274
00275
00276
00277 if(receiver == PROCESS_BROADCAST) {
00278 for(p = process_list; p != NULL; p = p->next) {
00279
00280
00281
00282 if(poll_requested) {
00283 do_poll();
00284 }
00285 call_process(p, ev, data);
00286 }
00287 } else {
00288
00289
00290
00291
00292 if(ev == PROCESS_EVENT_INIT) {
00293 receiver->state = PROCESS_STATE_RUNNING;
00294 }
00295
00296
00297 call_process(receiver, ev, data);
00298 }
00299 }
00300 }
00301
00302 int
00303 process_run(void)
00304 {
00305
00306 if(poll_requested) {
00307 do_poll();
00308 }
00309
00310
00311 do_event();
00312
00313 return nevents + poll_requested;
00314 }
00315
00316 int
00317 process_nevents(void)
00318 {
00319 return nevents + poll_requested;
00320 }
00321
00322 int
00323 process_post(struct process *p, process_event_t ev, process_data_t data)
00324 {
00325 static process_num_events_t snum;
00326
00327 if(PROCESS_CURRENT() == NULL) {
00328 PRINTF("process_post: NULL process posts event %d to process '%s', nevents %d\n",
00329 ev,PROCESS_NAME_STRING(p), nevents);
00330 } else {
00331 PRINTF("process_post: Process '%s' posts event %d to process '%s', nevents %d\n",
00332 PROCESS_NAME_STRING(PROCESS_CURRENT()), ev,
00333 p == PROCESS_BROADCAST? "<broadcast>": PROCESS_NAME_STRING(p), nevents);
00334 }
00335
00336 if(nevents == PROCESS_CONF_NUMEVENTS) {
00337 #if DEBUG
00338 if(p == PROCESS_BROADCAST) {
00339 printf("soft panic: event queue is full when broadcast event %d was posted from %s\n", ev, PROCESS_NAME_STRING(process_current));
00340 } else {
00341 printf("soft panic: event queue is full when event %d was posted to %s frpm %s\n", ev, PROCESS_NAME_STRING(p), PROCESS_NAME_STRING(process_current));
00342 }
00343 #endif
00344 return PROCESS_ERR_FULL;
00345 }
00346
00347 snum = (process_num_events_t)(fevent + nevents) % PROCESS_CONF_NUMEVENTS;
00348 events[snum].ev = ev;
00349 events[snum].data = data;
00350 events[snum].p = p;
00351 ++nevents;
00352
00353 #if PROCESS_CONF_STATS
00354 if(nevents > process_maxevents) {
00355 process_maxevents = nevents;
00356 }
00357 #endif
00358
00359 return PROCESS_ERR_OK;
00360 }
00361
00362 void
00363 process_post_synch(struct process *p, process_event_t ev, process_data_t data)
00364 {
00365 struct process *caller = process_current;
00366
00367 call_process(p, ev, data);
00368 process_current = caller;
00369 }
00370
00371 void
00372 process_poll(struct process *p)
00373 {
00374 if(p != NULL) {
00375 if(p->state == PROCESS_STATE_RUNNING ||
00376 p->state == PROCESS_STATE_CALLED) {
00377 p->needspoll = 1;
00378 poll_requested = 1;
00379 }
00380 }
00381 }
00382
00383 int
00384 process_is_running(struct process *p)
00385 {
00386 return p->state != PROCESS_STATE_NONE;
00387 }
00388
00389