Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/trunk/src/runtime/mp/solaris-mp.c
ViewVC logotype

Annotation of /sml/trunk/src/runtime/mp/solaris-mp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (view) (download) (as text)

1 : monnier 2 /* solaris-mp.c
2 :     *
3 :     * MP support for Sparc multiprocessor machines running Solaris 2.5
4 :     *
5 :     * Solaris implementation of externals defined in $(INCLUDE)/ml-mp.h
6 :     */
7 :    
8 :     #include <stdio.h>
9 :     #include <sys/mman.h>
10 :     #include <unistd.h>
11 :     #include <errno.h>
12 :     #include <thread.h>
13 :     #include <synch.h>
14 :     #include <sys/types.h>
15 :     #include <sys/processor.h>
16 :     #include <sys/procset.h>
17 :     #include "ml-limits.h"
18 :     #include "ml-values.h"
19 :     #include "ml-objects.h"
20 :     #include "tags.h"
21 :     #include "ml-mp.h"
22 :     #include "ml-state.h"
23 :     #include "ml-globals.h"
24 :     #include "vproc-state.h"
25 :    
26 :    
27 :     #define INT_MLinc(n,i) ((ml_val_t)INT_CtoML(INT_MLtoC(n) + (i)))
28 :     #define INT_MLdec(n,i) (INT_MLinc(n,(-i)))
29 :    
30 :     /* local functions */
31 :     PVT mp_lock_t AllocLock();
32 :     PVT mp_barrier_t *AllocBarrier();
33 :     PVT void *AllocArenaMem(int sz);
34 :     PVT void FreeArenaMem(void *, int);
35 :     PVT void *ProcMain(void *msp);
36 :     PVT void *ResumeProc(void *vmsp);
37 :     PVT void SuspendProc(ml_state_t *msp);
38 :     PVT ml_state_t **InitProcStatesArray();
39 :     PVT void BindToRealProc(processorid_t *);
40 :    
41 :     /* locals */
42 :     PVT caddr_t arena; /* arena for shared sync objects */
43 :     PVT mp_lock_t arenaLock; /* must be held to alloc/free a lock */
44 :     PVT mp_lock_t MP_ProcLock; /* must be used to acquire/release procs */
45 :     PVT ml_state_t **procStates; /*[MAX_NUM_PROCS]*/ /* list of states of suspended
46 :     procs */
47 :     #if defined(MP_PROFILE)
48 :     PVT int *doProfile;
49 :     #endif
50 :    
51 :     #define LEAST_PROCESSOR_ID 0
52 :     #define GREATEST_PROCESSOR_ID 3
53 :    
54 :     #define NextProcessorId(id) (((id) == GREATEST_PROCESSOR_ID) ? LEAST_PROCESSOR_ID : (id) + 1)
55 :    
56 :     PVT processorid_t *processorId; /* processor id of the next processor a lwp
57 :     will be bound to */
58 :     /* globals */
59 :     mp_lock_t MP_GCLock;
60 :     mp_lock_t MP_GCGenLock;
61 :     mp_barrier_t *MP_GCBarrier;
62 :     mp_lock_t MP_TimerLock;
63 :    
64 :     #if defined(MP_PROFILE)
65 :     int mutex_trylock_calls;
66 :     int trylock_calls;
67 :     #endif
68 :    
69 :     /* MP_Init:
70 :     */
71 :     void MP_Init()
72 :     {
73 :     int fd;
74 :    
75 :     if ((fd = open("/dev/zero",O_RDWR)) == -1)
76 :     Die("MP_Init:Couldn't open /dev/zero");
77 :    
78 :     arena = mmap((caddr_t) 0, sysconf(_SC_PAGESIZE),PROT_READ | PROT_WRITE ,MAP_PRIVATE,fd,0);
79 :    
80 :     arenaLock = AllocLock();
81 :     MP_ProcLock = AllocLock();
82 :     MP_GCLock = AllocLock();
83 :     MP_GCGenLock = AllocLock();
84 :     MP_TimerLock = AllocLock();
85 :     MP_GCBarrier = AllocBarrier();
86 :     procStates = InitProcStatesArray();
87 :     ASSIGN(ActiveProcs, INT_CtoML(1));
88 :     #ifdef MP_NONBLOCKING_IO
89 :     MP_InitStdInReader ();
90 :     #endif
91 :     processorId = (processorid_t *) AllocArenaMem(sizeof(processorid_t));
92 :     *processorId = -1;
93 :     BindToRealProc(processorId);
94 :    
95 :     #ifdef MP_PROFILE
96 :     doProfile = (int *) AllocArenaMem(sizeof(int));
97 :     *doProfile = 0;
98 :     #endif
99 :     NextProcessorId(*processorId);
100 :    
101 :     /* thr_setconcurrency(MAX_NUM_PROCS); */
102 :    
103 :     } /* end of MP_Init */
104 :    
105 :     /*************************************************************************
106 :     * Function: PVT mp_state_t **InitProcStatesArray()
107 :     * Purpose: Initialize the array of pointers to ml states of suspended
108 :     * processors
109 :     * Return: The initialized array as a pointer to pointers.
110 :     *************************************************************************/
111 :     PVT ml_state_t **InitProcStatesArray()
112 :     {
113 :     ml_state_t **array;
114 :     ml_state_t **ptr;
115 :     int i;
116 :    
117 :     array = (ml_state_t **) AllocArenaMem(sizeof(ml_state_t *));
118 :    
119 :     for (i=1; i < MAX_NUM_PROCS; i++)
120 :     {
121 :     ptr = (ml_state_t **) AllocArenaMem(sizeof(ml_state_t *));
122 :     *ptr = (ml_state_t *) NULL;
123 :     ptr++;
124 :     }
125 :    
126 :     return (array);
127 :    
128 :     } /* end of InitProcStatesArray */
129 :     /*************************************************************************
130 :     * Function: PVT mp_lock_t AllocLock()
131 :     * Purpose: Allocate a portion of the arena of synch objects for a spin
132 :     lock.
133 :     * Returns: returns a pointer to the allocated region.
134 :     * Created: 5-14-96
135 :     *************************************************************************/
136 :     PVT mp_lock_t AllocLock()
137 :     {
138 :     mp_lock_t lock;
139 :    
140 :     lock = (mp_lock_t) AllocArenaMem(MP_LOCK_SZ);
141 :    
142 :     lock->value = UNSET;
143 :    
144 :     if (mutex_init(&lock->mutex, USYNC_THREAD, NULL) == -1)
145 :     Die("AllocLock: unable to initialize mutex");
146 :    
147 :     return lock;
148 :    
149 :     } /* end of AllocLock */
150 :    
151 :     /**************************************************************************
152 :     * Function: FreeLock
153 :     * Purpose : Destroy the mutex. In addition, if the lock was the last object
154 :     allocated in the arena then recapture the space occupied by the
155 :     lock. Otherwise, zero out the space occupied by the lock.
156 :     * Created : 5-14-96
157 :     **************************************************************************/
158 :     PVT void FreeLock(mp_lock_t lock)
159 :     {
160 :     #if defined(MP_LOCK_DEBUG)
161 :     printf("arena = %ld\t lock = %ld\n",(int) arena, lock);
162 :     #endif
163 :    
164 :     mutex_destroy(&lock->mutex);
165 :    
166 :     FreeArenaMem(lock,MP_LOCK_SZ);
167 :    
168 :     } /* end of FreeLock */
169 :    
170 :     /*************************************************************************
171 :     * Function: void BindToRealProc(processorid_t *)
172 :     * Purpose: Bind the current lwp to a real processor. Attempt to bind the
173 :     lwp to a processor different from the last processor a lwp was
174 :     bound to.
175 :     * Created: 7-22-96
176 :     *************************************************************************/
177 :     void BindToRealProc(processorid_t *processorId)
178 :     {
179 :     processorid_t procId = *processorId;
180 :     processorid_t obind;
181 :     int lwpBoundP = 0;
182 :    
183 :     while (!lwpBoundP)
184 :     {
185 :     procId = NextProcessorId(procId);
186 :     if (procId == *processorId) /* attempts made to bind on all processors */
187 :     {
188 :     fprintf(stderr, "lwp was not bound to a processor.\n");
189 :     lwpBoundP = 1;
190 :     }
191 :     else
192 :     {
193 :     if (processor_bind(P_LWPID, P_MYID, procId, &obind) == -1)
194 :     {
195 :     fprintf(stderr, "error attempting to bind lwp to processor [%d]\n",(int) procId);
196 :     lwpBoundP = 1;
197 :     }
198 :     else
199 :     {
200 :     if (obind == PBIND_NONE) /* couldn't bind to lwp */
201 :     fprintf(stderr, "couldn't bind current lwp to processor [%d]\n", (int) procId);
202 :     else
203 :     {
204 :     fprintf(stderr,"lwp bound to processor [%d]\n",procId);
205 :     lwpBoundP = 1;
206 :     *processorId = procId;
207 :     }
208 :     }
209 :     }
210 :     }
211 :    
212 :     } /* end of BindToRealProc */
213 :    
214 :     /*************************************************************************
215 :     * Function: bool_t MP_TryLock(mp_lock_t lock)
216 :     * Purpose: Return FALSE if cannot set lock; otherwise set lock and return
217 :     TRUE.
218 :     * Created: 5-14-96
219 :     * Invariant: If more than one processes calls MP_TryLock at the same time,
220 :     then only one of the processes will have TRUE returned.
221 :     *************************************************************************/
222 :    
223 :     bool_t MP_TryLock(mp_lock_t lock)
224 :     {
225 :     #if defined(MP_PROFILE)
226 :     long cpuTime;
227 :     #endif
228 :    
229 :     #if defined(MP_LOCK_DEBUG)
230 :     printf("MP_TryLock: lock value is %d\n",lock->value);
231 :     #endif
232 :    
233 :     #if defined(MP_PROFILE)
234 :     if (*doProfile)
235 :     {
236 :     cpuTime = (long) clock();
237 :     printf("trylock_calls = %d\n",++trylock_calls);
238 :     }
239 :     #endif
240 :    
241 :     /* We test to see if the lock is set here so that we can reduce the number
242 :     of calls to mutex_trylock when we are waiting for the lock to be
243 :     released. Apparently repeated calls to mutex_trylock floods the bus.
244 :     I don't know why. I found this out from the Threads Primer book.
245 :     */
246 :     if (lock->value == SET)
247 :     #if defined(MP_PROFILE)
248 :     {
249 :     if (*doProfile)
250 :     fprintf(stderr,"MP_Trylock:cpu time %ld\n",(long) clock() - cpuTime);
251 :     return(FALSE);
252 :     }
253 :     #else
254 :     return(FALSE);
255 :     #endif
256 :     else
257 :     {
258 :     #if defined(MP_LOCK_DEBUG)
259 :     printf("MP_TryLock: calling mutex_trylock\n");
260 :     #endif
261 :    
262 :     #if defined(MP_PROFILE)
263 :     if (*doProfile)
264 :     printf("mutex_trylock_calls = %d\n",++mutex_trylock_calls);
265 :     #endif
266 :    
267 :     if (mutex_trylock(&lock->mutex) == EBUSY)
268 :     #if defined(MP_PROFILE)
269 :     if (*doProfile)
270 :     fprintf(stderr,"MP_Trylock:cpu time %ld\n",(long) clock() - cpuTime);
271 :     #else
272 :     return(FALSE);
273 :     #endif
274 :     else
275 :     {
276 :     if (lock->value == SET)
277 :     {
278 :     mutex_unlock(&lock->mutex);
279 :     #if defined(MP_PROFILE)
280 :     if (*doProfile)
281 :     fprintf(stderr,"MP_Trylock:cpu time %ld\n",(long) clock() - cpuTime);
282 :     #endif
283 :     return(FALSE);
284 :     }
285 :    
286 :     lock->value = SET;
287 :     mutex_unlock(&lock->mutex);
288 :     #if defined(MP_PROFILE)
289 :     if (*doProfile)
290 :     fprintf(stderr,"MP_Trylock:cpu time %ld\n",(long) clock() - cpuTime);
291 :     #endif
292 :     return(TRUE);
293 :     }
294 :     }
295 :     } /* end of MP_TryLock */
296 :    
297 :    
298 :     /*************************************************************************
299 :     * Function: void MP_UnsetLock(mp_lock_t lock)
300 :     * Purpose: Assign lock->value the value of 0.
301 :     * Created: 5-14-96
302 :     *************************************************************************/
303 :    
304 :     void MP_UnsetLock(mp_lock_t lock)
305 :     {
306 :     lock->value = UNSET;
307 :     }
308 :    
309 :     /*************************************************************************
310 :     * Function: void MP_SetLock(mp_lock_t lock)
311 :     * Purpose: Busy wait until able set the lock.
312 :     * Created: 5-14-96
313 :     *************************************************************************/
314 :     void MP_SetLock(mp_lock_t lock)
315 :     {
316 :     while (MP_TryLock(lock) == FALSE) ;
317 :     }
318 :    
319 :    
320 :     /* MP_AllocLock:
321 :     */
322 :     mp_lock_t MP_AllocLock()
323 :     {
324 :     mp_lock_t lock;
325 :    
326 :     MP_SetLock(arenaLock);
327 :     lock = AllocLock();
328 :     MP_UnsetLock(arenaLock);
329 :    
330 :     return lock;
331 :     } /* end of MP_AllocLock */
332 :    
333 :     /*************************************************************************
334 :     * Function: void MP_FreeLock (mp_lock_t lock)
335 :     * Purpose: Destroy mutex of lock and free memory occupied by lock.
336 :     * Returns: returns non-negative int if OK, -1 on error
337 :     * Created: 5-13-96
338 :     *************************************************************************/
339 :    
340 :     void MP_FreeLock (mp_lock_t lock)
341 :     {
342 :     MP_SetLock(arenaLock);
343 :     FreeLock(lock);
344 :     MP_UnsetLock(arenaLock);
345 :     }
346 :    
347 :     /*************************************************************************
348 :     * Function: AllocBarrier
349 :     * Purpose: Get a chunk of memory from the arena for a barrier and
350 :     initialize it.
351 :     * Returns: Return a pointer to the barrier.
352 :     * Created: 5-15-96
353 :     *************************************************************************/
354 :    
355 :     PVT mp_barrier_t *AllocBarrier ()
356 :     {
357 :     mp_barrier_t *barrierp;
358 :    
359 :     barrierp = (mp_barrier_t *) arena;
360 :     arena += MP_BARRIER_SZ;
361 :    
362 :     barrierp->n_waiting = 0;
363 :     barrierp->phase = 0;
364 :    
365 :     if (mutex_init(&barrierp->lock, USYNC_THREAD, NULL) == -1)
366 :     Die("MP_Barrier: could not init barrier mutex lock");
367 :    
368 :     if (cond_init(&barrierp->wait_cv, USYNC_THREAD, NULL) == -1)
369 :     Die("MP_Barrier: could not init conditional var of barrier");
370 :    
371 :    
372 :     return barrierp;
373 :    
374 :     } /* end of AllocBarrier */
375 :    
376 :    
377 :     /*************************************************************************
378 :     * Function: MP_AllocBarrier
379 :     * Purpose: Allocate a barrier from the synch object arena. Allocation is
380 :     mutually exclusive. Note the barrier is not initialized.
381 :     * Returns: Return a pointer to the barrier.
382 :     * Created: 5-15-96
383 :     *************************************************************************/
384 :     mp_barrier_t *MP_AllocBarrier ()
385 :     {
386 :     mp_barrier_t *barrierp;
387 :    
388 :     MP_SetLock(arenaLock);
389 :     barrierp = AllocBarrier ();
390 :     MP_UnsetLock(arenaLock);
391 :    
392 :     return barrierp;
393 :    
394 :     } /* end of MP_AllocBarrier */
395 :    
396 :     /*************************************************************************
397 :     * Function: MP_AllocBarrier
398 :     * Purpose: destroy mutex and conditional variables of the barrier.
399 :     Regain memory if barrier was last object allocated in arena;
400 :     otherwise zero out the memory occupied by the barrier.
401 :     * Returns: Nothing.
402 :     * Created: 5-15-96
403 :     *************************************************************************/
404 :     void FreeBarrier(mp_barrier_t *barrierp)
405 :     {
406 :     mutex_destroy(&barrierp->lock);
407 :     cond_destroy(&barrierp->wait_cv);
408 :    
409 :     FreeArenaMem(barrierp, MP_BARRIER_SZ);
410 :     } /* end of FreeBarrier */
411 :    
412 :     void MP_FreeBarrier(mp_barrier_t *barrierp)
413 :     {
414 :     MP_SetLock(arenaLock);
415 :     FreeBarrier(barrierp);
416 :     MP_UnsetLock(arenaLock);
417 :     } /* end of MP_FreeBarrier */
418 :    
419 :    
420 :     /*************************************************************************
421 :     * Function: MP_Barrier
422 :     * Purpose: Wait until the required number of threads enter the barrier.
423 :     * Returns: Nothing.
424 :     * Created: 5-15-96
425 :     * Invariant: barrierp->n_waiting <= n_clients
426 :     *************************************************************************/
427 :    
428 :     void MP_Barrier(mp_barrier_t *barrierp, unsigned n_clients)
429 :     {
430 :     int my_phase;
431 :    
432 :     mutex_lock(&barrierp->lock);
433 :    
434 :     my_phase = barrierp->phase;
435 :     barrierp->n_waiting++;
436 :    
437 :     if (barrierp->n_waiting == n_clients)
438 :     {
439 :     barrierp->n_waiting = 0;
440 :     barrierp->phase = 1 - my_phase;
441 :     cond_broadcast(&barrierp->wait_cv);
442 :     }
443 :    
444 :     /* Wait for the end of this synchronization phase */
445 :     while (barrierp->phase == my_phase)
446 :     {
447 :     cond_wait(&barrierp->wait_cv, &barrierp->lock);
448 :     }
449 :    
450 :     mutex_unlock(&barrierp->lock);
451 :    
452 :     } /* end of MP_Barrier */
453 :    
454 :     /*************************************************************************
455 :     * Function: MP_ResetBarrier
456 :     * Purpose: Set the various values of the barrier to zero.
457 :     * Returns: Nothing.
458 :     * Created: 5-15-96
459 :     *************************************************************************/
460 :     void MP_ResetBarrier(mp_barrier_t *barrierp)
461 :     {
462 :     barrierp->n_waiting = 0;
463 :     barrierp->phase = 0;
464 :    
465 :     } /* end of MP_ResetBarrier */
466 :    
467 :    
468 :    
469 :     /*************************************************************************
470 :     * Function: AllocArenaMem
471 :     ************************************************************************/
472 :    
473 :     PVT void *AllocArenaMem(int sz)
474 :     {
475 :     void *obj;
476 :    
477 :     obj = arena;
478 :     arena += sz;
479 :    
480 :     return obj;
481 :     }
482 :    
483 :     /*************************************************************************
484 :     * Function: FreeArenaMem
485 :     ************************************************************************/
486 :     PVT void FreeArenaMem(void *p, int sz)
487 :     {
488 :     if (arena == (caddr_t) p + sz)
489 :     arena -= sz;
490 :     else
491 :     memset(p,0,sz);
492 :     }
493 :    
494 :     /*************************************************************************
495 :     * Function: ResumeProc(ml_state_t *msp)
496 :     * Purpose: Resumes a proc to either perform garbage collection or to
497 :     * run ml with the given ml state.
498 :     * Return: Nothing
499 :     ************************************************************************/
500 :     PVT void *ResumeProc(void *vmsp)
501 :     {
502 :     ml_state_t *msp = (ml_state_t *) vmsp;
503 :    
504 :     MP_SetLock(MP_ProcLock);
505 :     if (msp->ml_vproc->vp_mpState == MP_PROC_SUSPENDED)
506 :     {
507 :     /* proc only resumed to do a gc */
508 :     #ifdef MP_DEBUG
509 :     SayDebug("resuming %d to perform a gc\n",msp->ml_vproc->vp_mpSelf);
510 :     #endif
511 :     msp->ml_vproc->vp_mpState == MP_PROC_GC;
512 :     MP_UnsetLock(MP_ProcLock);
513 :    
514 :     /* the GC will be performed when we call MP_ReleaseProc */
515 :    
516 :     MP_ReleaseProc(msp);
517 :     }
518 :     else
519 :     {
520 :     #ifdef MP_DEBUG
521 :     SayDebug("[release_proc: resuming proc %d]\n",msp->ml_vproc->vp_mpSelf);
522 :     #endif
523 :     MP_UnsetLock(MP_ProcLock);
524 :     RunML(msp);
525 :     Die ("return after RunML(msp) in mp_release_proc\n");
526 :     }
527 :     } /* end of ResumeProc */
528 :    
529 :     /*************************************************************************
530 :     * Function: MP_ResumeVProcs(int n_procs)
531 :     * Purpose: Remove n_procs states from the list of states and spawn threads
532 :     * to execute them.
533 :     * Note: We assume that calls to this function are mutually exclusive.
534 :     * Return: Return a pointer to the last state resumed.
535 :     ************************************************************************/
536 :     vproc_state_t *MP_ResumeVProcs(int n_procs)
537 :     {
538 :     ml_state_t *statep;
539 :     int i = 0;
540 :    
541 :     while(i < MAX_NUM_PROCS && n_procs > 0) {
542 :    
543 :     if ((statep = procStates[i]) != (ml_state_t *) NULL) /* get a state */
544 :     {
545 :     /* spawn a thread to execute the state */
546 :     #ifdef MP_DEBUG
547 :     SayDebug("Resuming proc %d\n",statep->ml_vproc->vp_mpSelf);
548 :     #endif
549 :     if(thr_create(NULL,0,ResumeProc,(void *)statep,NULL,NULL) != 0)
550 :     Die("Could create a thread to resume processors");
551 :    
552 :     procStates[i] = NULL;
553 :     i++;
554 :     n_procs--;
555 :     }
556 :     else
557 :     i++;
558 :     }
559 :    
560 :     if (statep == (ml_state_t *) NULL)
561 :     return (vproc_state_t *) NULL;
562 :    
563 :     return statep->ml_vproc;
564 :    
565 :     } /* end of MP_ResumeVProcs */
566 :    
567 :     /*************************************************************************
568 :     * Function: SuspendProc(ml_state_t *msp)
569 :     * Purpose: Suspend the calling proc, add its state, msp, to the suspended
570 :     * proc state list, and kill the thread the proc is running on.
571 :     * Return: Nothing.
572 :     ************************************************************************/
573 :     PVT void SuspendProc(ml_state_t *msp)
574 :     {
575 :     int i=0;
576 :    
577 :     MP_SetLock(MP_ProcLock);
578 :    
579 :     /* check if proc has actually been suspended */
580 :    
581 :     if (msp->ml_vproc->vp_mpState != MP_PROC_SUSPENDED)
582 :     {
583 :     #ifdef MP_DEBUG
584 :     SayDebug("proc state is not PROC_SUSPENDED; not suspended");
585 :     #endif
586 :     MP_UnsetLock(MP_ProcLock);
587 :     return;
588 :     }
589 :    
590 :    
591 :     while (i < MAX_NUM_PROCS) {
592 :     if (procStates[i] == NULL)
593 :     {
594 :     procStates[i] = msp;
595 :     i = MAX_NUM_PROCS;
596 :     }
597 :     else
598 :     i++;
599 :     }
600 :    
601 :     MP_UnsetLock(MP_ProcLock);
602 :    
603 :     /* exit the thread */
604 :     thr_exit(NULL);
605 :    
606 :     } /* end of SuspendProc */
607 :    
608 :     /*************************************************************************
609 :     * Function: MP_ReleaseProc(ml_state_t *msp)
610 :     ************************************************************************/
611 :     void MP_ReleaseProc(ml_state_t *msp)
612 :     {
613 :    
614 :    
615 :     InvokeGC(msp,1);
616 :    
617 :     MP_SetLock(MP_ProcLock);
618 :     msp->ml_vproc->vp_mpState = MP_PROC_SUSPENDED;
619 :     MP_UnsetLock(MP_ProcLock);
620 :    
621 :     /* suspend the proc */
622 :     #ifdef MP_DEBUG
623 :     SayDebug("suspending proc %d\n",msp->ml_vproc->vp_mpSelf);
624 :     #endif
625 :     SuspendProc(msp);
626 :    
627 :     } /* end of MP_ReleaseProc */
628 :    
629 :     /*************************************************************************
630 :     * Function: ProcMain(ml_state_t *msp)
631 :     * Purpose: Invoke RunML on msp; die if RunML returns
632 :     ************************************************************************/
633 :     PVT void *ProcMain(void *vmsp)
634 :     {
635 :     ml_state_t *msp = (ml_state_t *) vmsp;
636 :    
637 :     /* spin until we get our id (from return of call to thr_create) */
638 :     while (msp->ml_vproc->vp_mpSelf == NIL(mp_pid_t)) {
639 :     #ifdef MP_DEBUG
640 :     SayDebug("[waiting for self]\n");
641 :     #endif
642 :     continue;
643 :     }
644 :     #ifdef MP_DEBUG
645 :     SayDebug ("[new proc main: releasing lock]\n");
646 :     #endif
647 :    
648 :     BindToRealProc(processorId);
649 :    
650 :     MP_UnsetLock(MP_ProcLock); /* implicitly handed to us by the parent */
651 :     RunML(msp); /* should never return */
652 :     Die("proc returned after run_ml() in ProcMain().\n");
653 :    
654 :     } /* end of ProcMain */
655 :     /*************************************************************************
656 :     * Function: MP_AcquireProc(ml_state_t *msp, ml_val_t arg)
657 :     ************************************************************************/
658 :     ml_val_t MP_AcquireProc(ml_state_t *msp, ml_val_t arg)
659 :     {
660 :     ml_state_t *p;
661 :     vproc_state_t *vsp;
662 :     ml_val_t v = REC_SEL(arg, 0);
663 :     ml_val_t f = REC_SEL(arg, 1);
664 :     int i;
665 :    
666 :     #ifdef MP_DEBUG
667 :     SayDebug("[acquiring proc]\n");
668 :     #endif
669 :    
670 :     MP_SetLock(MP_ProcLock);
671 :    
672 :     /* search for a suspended proc to reuse */
673 :     for (i = 0;
674 :     (i < NumVProcs) && (VProc[i]->vp_mpState != MP_PROC_SUSPENDED);
675 :     i++)
676 :     continue;
677 :    
678 :     #ifdef MP_DEBUG
679 :     SayDebug("[checking for suspended processor]\n");
680 :     #endif
681 :     if (i == NumVProcs)
682 :     {
683 :     if (DEREF(ActiveProcs) == INT_CtoML(MAX_NUM_PROCS))
684 :     {
685 :     MP_UnsetLock(MP_ProcLock);
686 :     Error("[processors maxed]\n");
687 :     return ML_false;
688 :     }
689 :     #ifdef MP_DEBUG
690 :     SayDebug("[checking for NO_PROC]\n");
691 :     #endif
692 :    
693 :     /* search for a slot in which to put a new proc */
694 :     for (i = 0;
695 :     (i < NumVProcs) && (VProc[i]->vp_mpState != MP_PROC_NO_PROC);
696 :     i++)
697 :     continue;
698 :    
699 :     if (i == NumVProcs)
700 :     {
701 :     MP_UnsetLock(MP_ProcLock);
702 :     Error("[no processor to allocate]\n");
703 :     return ML_false;
704 :     }
705 :    
706 :     /* use processor at index i */
707 :     vsp = VProc[i];
708 :    
709 :     } /* end of then */
710 :    
711 :     else /* using a suspended processor */
712 :     {
713 :     #ifdef MP_DEBUG
714 :     SayDebug("[using a suspended processor]\n");
715 :     #endif
716 :     vsp = MP_ResumeVProcs(1);
717 :     }
718 :    
719 :     p = vsp->vp_state;
720 :    
721 :     p->ml_exnCont = PTR_CtoML(handle_v+1);
722 :     p->ml_arg = ML_unit;
723 :     p->ml_cont = PTR_CtoML(return_c);
724 :     p->ml_closure = f;
725 :     p->ml_pc =
726 :     p->ml_linkReg = GET_CODE_ADDR(f);
727 :     p->ml_varReg = v;
728 :    
729 :     if (vsp->vp_mpState == MP_PROC_NO_PROC)
730 :     {
731 :     mp_pid_t procId;
732 :    
733 :     /* assume we get one */
734 :     ASSIGN(ActiveProcs, INT_MLinc(DEREF(ActiveProcs), 1));
735 :     if (thr_create(NULL,0,ProcMain,(void *)p,THR_NEW_LWP,&((thread_t) procId)) == 0)
736 :     {
737 :     #ifdef MP_DEBUG
738 :     SayDebug ("[got a processor: %d,]\n",procId);
739 :     #endif
740 :     vsp->vp_mpState = MP_PROC_RUNNING;
741 :     vsp->vp_mpSelf = procId;
742 :     /* NewProc will release MP_ProcLock */
743 :     return ML_true;
744 :     }
745 :     else
746 :     {
747 :     ASSIGN(ActiveProcs, INT_MLdec(DEREF(ActiveProcs), 1));
748 :     MP_UnsetLock(MP_ProcLock);
749 :     return ML_false;
750 :     }
751 :     }
752 :     else
753 :     {
754 :     /* the thread executing the processor has already been invoked */
755 :     vsp->vp_mpState = MP_PROC_RUNNING;
756 :     #ifdef MP_DEBUG
757 :     SayDebug ("[reusing a processor %d]\n",vsp->vp_mpSelf);
758 :     #endif
759 :     MP_UnsetLock(MP_ProcLock);
760 :     return ML_true;
761 :     }
762 :    
763 :     } /* end of MP_AcquireProc */
764 :    
765 :    
766 :     /*************************************************************************
767 :     * Function: MP_Shutdown
768 :     ************************************************************************/
769 :     void MP_Shutdown ()
770 :     {
771 :     munmap(arena,sysconf(_SC_PAGESIZE));
772 :     } /* end of MP_Shutdown */
773 :    
774 :    
775 :     /*************************************************************************
776 :     * Function: MP_MaxProcs
777 :     ************************************************************************/
778 :     int MP_MaxProcs ()
779 :     {
780 :     return MAX_NUM_PROCS;
781 :    
782 :     } /* end of MP_MaxProcs */
783 :    
784 :     /*************************************************************************
785 :     * Function: MP_ProcId
786 :     ************************************************************************/
787 :     mp_pid_t MP_ProcId ()
788 :     {
789 :    
790 :     return (thr_self());
791 :    
792 :     } /* end of MP_ProcId */
793 :    
794 :     /*************************************************************************
795 :     * Function: MP_ActiveProcs
796 :     ************************************************************************/
797 :     int MP_ActiveProcs ()
798 :     {
799 :     int ap;
800 :    
801 :     MP_SetLock(MP_ProcLock);
802 :     ap = INT_MLtoC(DEREF(ActiveProcs));
803 :     MP_UnsetLock(MP_ProcLock);
804 :    
805 :     return ap;
806 :    
807 :     } /* end of MP_ActiveProcs */
808 :    
809 :    
810 :     /* EndSourceFile */
811 :    

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0