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 #ifdef PROCESS_CONF_FASTPOLL
00070 #define NPOLLS PROCESS_CONF_FASTPOLL
00071 #include <signal.h>
00072 static volatile unsigned npolls;
00073 static struct process *needpoll[NPOLLS];
00074 #endif
00075 static process_num_events_t nevents, fevent;
00076 static struct event_data events[PROCESS_CONF_NUMEVENTS];
00077
00078 static volatile unsigned char poll_requested;
00079
00080 #define PROCESS_STATE_NONE 0
00081 #define PROCESS_STATE_INIT 1
00082 #define PROCESS_STATE_RUNNING 2
00083 #define PROCESS_STATE_NEEDS_POLL 3
00084
00085 static void call_process(struct process *p, process_event_t ev, process_data_t data);
00086
00087
00088
00089 process_event_t
00090 process_alloc_event(void)
00091 {
00092 return lastevent++;
00093 }
00094
00095 void
00096 process_start(struct process *p, char *arg)
00097 {
00098 struct process *q;
00099
00100
00101
00102 for(q = process_list; q != p && q != NULL; q = q->next);
00103
00104
00105 if(q == p) {
00106 return;
00107 }
00108
00109 p->next = process_list;
00110 process_list = p;
00111
00112 p->state = PROCESS_STATE_INIT;
00113
00114 PT_INIT(&p->pt);
00115
00116
00117 process_post(p, PROCESS_EVENT_INIT, (process_data_t)arg);
00118 }
00119
00120 static void
00121 exit_process(struct process *p, struct process *fromprocess)
00122 {
00123 register struct process *q;
00124 struct process *old_current = process_current;
00125
00126 if(p->state != PROCESS_STATE_NONE) {
00127
00128 p->state = PROCESS_STATE_NONE;
00129
00130
00131
00132
00133
00134
00135 for(q = process_list; q != NULL; q = q->next) {
00136 if(p != q) {
00137 call_process(q, PROCESS_EVENT_EXITED, (process_data_t)p);
00138 }
00139 }
00140
00141 if(p->thread != NULL && p != fromprocess) {
00142
00143 process_current = p;
00144 p->thread(&p->pt, PROCESS_EVENT_EXIT, NULL);
00145 }
00146 }
00147
00148 if(p == process_list) {
00149 process_list = process_list->next;
00150 } else {
00151 for(q = process_list; q != NULL; q = q->next) {
00152 if(q->next == p) {
00153 q->next = p->next;
00154 break;
00155 }
00156 }
00157 }
00158
00159 {
00160 int n;
00161 int i = fevent;
00162 for(n = nevents; n > 0; n--) {
00163 if(events[i].p == p) {
00164 events[i].p = PROCESS_ZOMBIE;
00165 #if 0
00166 printf("soft panic: exiting process has remaining event 0x%x\n",
00167 events[i].ev);
00168 #endif
00169 }
00170 i = (i + 1) % PROCESS_CONF_NUMEVENTS;
00171 }
00172 #ifdef NPOLLS
00173 for(i = 0; i < NPOLLS && i < npolls; i++) {
00174 if(needpoll[i] == p) {
00175 needpoll[i] = PROCESS_ZOMBIE;
00176 }
00177 }
00178 #endif
00179 }
00180 process_current = old_current;
00181 }
00182
00183 static void
00184 call_process(struct process *p, process_event_t ev, process_data_t data)
00185 {
00186 int ret;
00187
00188 if((p->state == PROCESS_STATE_RUNNING ||
00189 p->state == PROCESS_STATE_NEEDS_POLL) &&
00190 p->thread != NULL) {
00191 process_current = p;
00192
00193 ret = p->thread(&p->pt, ev, data);
00194 if(ret == PT_EXITED ||
00195 ret == PT_ENDED ||
00196 ev == PROCESS_EVENT_EXIT) {
00197 exit_process(p, p);
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
00215 process_current = process_list = NULL;
00216 }
00217
00218
00219
00220
00221
00222 static void
00223 do_poll(void)
00224 {
00225 struct process *p;
00226
00227 poll_requested = 0;
00228
00229 #ifdef NPOLLS
00230 unsigned i;
00231 int s;
00232
00233
00234 for(i = 0; i < npolls; i++) {
00235 do_more:
00236 if(i == NPOLLS) {
00237 goto slowpoll;
00238 }
00239 if(needpoll[i] != PROCESS_ZOMBIE
00240 && needpoll[i]->state == PROCESS_STATE_NEEDS_POLL) {
00241 needpoll[i]->state = PROCESS_STATE_RUNNING;
00242 call_process(needpoll[i], PROCESS_EVENT_POLL, NULL);
00243 }
00244 }
00245 s = splhigh();
00246 if(i == npolls) {
00247 npolls = 0;
00248 splx(s);
00249 return;
00250 }
00251 splx(s);
00252 goto do_more;
00253
00254
00255 slowpoll:
00256
00257 npolls = 0;
00258 #endif
00259
00260 for(p = process_list; p != NULL; p = p->next) {
00261
00262 if(p->state == PROCESS_STATE_NEEDS_POLL) {
00263 p->state = PROCESS_STATE_RUNNING;
00264 call_process(p, PROCESS_EVENT_POLL, NULL);
00265 }
00266
00267 #if 0
00268
00269
00270 if(poll_requested) {
00271 poll_requested = 0;
00272 p = process_list;
00273 }
00274 #endif
00275 }
00276 }
00277
00278
00279
00280
00281
00282
00283 static void
00284 do_event(void)
00285 {
00286 static process_event_t ev;
00287 static process_data_t data;
00288 static struct process *receiver;
00289 static struct process *p;
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 if(nevents > 0) {
00300
00301
00302 ev = events[fevent].ev;
00303
00304 data = events[fevent].data;
00305 receiver = events[fevent].p;
00306
00307
00308
00309 fevent = (fevent + 1) % PROCESS_CONF_NUMEVENTS;
00310 --nevents;
00311
00312
00313
00314 if(receiver == PROCESS_BROADCAST) {
00315 for(p = process_list; p != NULL; p = p->next) {
00316
00317
00318
00319 if(poll_requested) {
00320 do_poll();
00321 }
00322 call_process(p, ev, data);
00323 }
00324 } else if(receiver == PROCESS_ZOMBIE) {
00325
00326 } else {
00327
00328
00329
00330
00331 if(ev == PROCESS_EVENT_INIT) {
00332 receiver->state = PROCESS_STATE_RUNNING;
00333 }
00334
00335
00336 call_process(receiver, ev, data);
00337 }
00338 }
00339 }
00340
00341 int
00342 process_run(void)
00343 {
00344
00345 if(poll_requested) {
00346 do_poll();
00347 }
00348
00349
00350 do_event();
00351
00352 return nevents + poll_requested;
00353 }
00354
00355 int
00356 process_post(struct process *p, process_event_t ev, process_data_t data)
00357 {
00358 static unsigned char snum;
00359
00360 if(nevents == PROCESS_CONF_NUMEVENTS) {
00361 printf("soft panic: event queue is full\n");
00362 return PROCESS_ERR_FULL;
00363 }
00364
00365 snum = (fevent + nevents) % PROCESS_CONF_NUMEVENTS;
00366 events[snum].ev = ev;
00367 events[snum].data = data;
00368 events[snum].p = p;
00369 ++nevents;
00370
00371 return PROCESS_ERR_OK;
00372 }
00373
00374 void
00375 process_post_synch(struct process *p, process_event_t ev, process_data_t data)
00376 {
00377 struct process *caller = process_current;
00378
00379 call_process(p, ev, data);
00380 process_current = caller;
00381 }
00382
00383 void
00384 process_poll(struct process *p)
00385 {
00386 if(p != NULL) {
00387 if(p->state == PROCESS_STATE_RUNNING) {
00388 p->state = PROCESS_STATE_NEEDS_POLL;
00389 poll_requested = 1;
00390 #ifdef NPOLLS
00391 int s = splhigh();
00392 if(npolls < NPOLLS) {
00393 needpoll[npolls] = p;
00394 }
00395 if(npolls != ~0u) npolls++;
00396 splx(s);
00397 #endif
00398 }
00399 }
00400 }
00401
00402