~ubuntu-branches/ubuntu/quantal/nspr/quantal-security

« back to all changes in this revision

Viewing changes to mozilla/nsprpub/pr/src/md/unix/solaris.c

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack, Fabien Tassin, Alexander Sack
  • Date: 2009-01-11 13:50:07 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20090111135007-butxlx6upwjcakod
Tags: 4.7.3-0ubuntu1
* New upstream version: 4.7.3 from NSPR_4_7_3_RTM tag

[ Fabien Tassin <fta@ubuntu.com> ]
* LP: #269188 - use /dev/urandom for better entropy on LTSP environments
* update diverged patches:
  - update debian/patches/30_pkgconfig.patch
  - update debian/patches/81_sonames.patch
  - update debian/patches/99_configure.patch

[ Alexander Sack <asac@ubuntu.com> ]
Drop debian soname patch for full upstream compatibility
* eliminate soname patch
  - delete debian/patches/81_sonames.patch
  - update debian/patches/series
* refresh configure patch to reflect dropped soname patch
  - update debian/patches/99_configure.patch
* install unversioned .so files
  - update debian/libnspr4-0d.install
* .so.0d links are not created without the soname patch. we create
  backlinks to the unversioned .so libs using debhelper; also we
  cannot dh_install the .0d versioned libs anymore and we drop
  them from .install accordingly
  - add debian/libnspr4-0d.links
  - update debian/libnspr4-0d.install
* implement link shuffeling transition (with abort cases) in
  maintainer scripts; affected libs: libnspr4.so libplc4.so libplds4.so
  - add debian/libnspr4-0d.postinst
  - add debian/libnspr4-0d.postrm
  - add debian/libnspr4-0d.preinst
  - add debian/libnspr4-0d.prerm
* drop soname version suffix from symbol files and reflect this fact by
  adjusting minimum version to this package version (4.7.3-0ubuntu1~)
  - update debian/libnspr4-0d.symbols
  - update debian/libnspr4-0d.symbols.amd64
  - update debian/libnspr4-0d.symbols.i386
  - update debian/libnspr4-0d.symbols.ia64
  - update debian/libnspr4-0d.symbols.lpia
  - update debian/libnspr4-0d.symbols.powerpc
* bump lower shlibs version constraint to 4.7.1+1.9-0ubuntu5~
  - update debian/rules
* rerun autoconf2.13 to apply dropped 81_sonames.patch to configure
  - update debian/patches/99_configure.patch
* explitly define libnspr4_0d_EXPORTED_LIBS and pass those manually
  to dpkg-gensymbols to workaround uncommon SONAME used by nspr libs
  - update debian/rules
* don't pretend to create shlibs-control file anymore; add binary
  lintian override for that
  - update debian/rules
* add #DEBHELPER# token to maintainer scripts
  - update debian/libnspr4-0d.postinst
  - update debian/libnspr4-0d.postrm
  - update debian/libnspr4-0d.preinst
  - update debian/libnspr4-0d.prerm

Show diffs side-by-side

added added

removed removed

Lines of Context:
86
86
}
87
87
#endif /* _PR_PTHREADS */
88
88
 
89
 
#if !defined(i386) && !defined(IS_64)
90
 
#if defined(_PR_HAVE_ATOMIC_OPS)
91
 
/* NOTE:
92
 
 * SPARC v9 (Ultras) do have an atomic test-and-set operation.  But
93
 
 * SPARC v8 doesn't.  We should detect in the init if we are running on
94
 
 * v8 or v9, and then use assembly where we can.
95
 
 *
96
 
 * This code uses the Solaris threads API.  It can be used in both the
97
 
 * pthreads and Solaris threads versions of nspr20 because "POSIX threads
98
 
 * and Solaris threads are fully compatible even within the same process",
99
 
 * to quote from pthread_create(3T).
100
 
 */
101
 
 
102
 
#include <thread.h>
103
 
#include <synch.h>
104
 
 
105
 
static mutex_t _solaris_atomic = DEFAULTMUTEX;
106
 
 
107
 
PRInt32
108
 
_MD_AtomicIncrement(PRInt32 *val)
109
 
{
110
 
    PRInt32 rv;
111
 
    if (mutex_lock(&_solaris_atomic) != 0)
112
 
        PR_ASSERT(0);
113
 
 
114
 
    rv = ++(*val);
115
 
 
116
 
    if (mutex_unlock(&_solaris_atomic) != 0)\
117
 
        PR_ASSERT(0);
118
 
 
119
 
        return rv;
120
 
}
121
 
 
122
 
PRInt32
123
 
_MD_AtomicAdd(PRInt32 *ptr, PRInt32 val)
124
 
{
125
 
    PRInt32 rv;
126
 
    if (mutex_lock(&_solaris_atomic) != 0)
127
 
        PR_ASSERT(0);
128
 
 
129
 
    rv = ((*ptr) += val);
130
 
 
131
 
    if (mutex_unlock(&_solaris_atomic) != 0)\
132
 
        PR_ASSERT(0);
133
 
 
134
 
        return rv;
135
 
}
136
 
 
137
 
PRInt32
138
 
_MD_AtomicDecrement(PRInt32 *val)
139
 
{
140
 
    PRInt32 rv;
141
 
    if (mutex_lock(&_solaris_atomic) != 0)
142
 
        PR_ASSERT(0);
143
 
 
144
 
    rv = --(*val);
145
 
 
146
 
    if (mutex_unlock(&_solaris_atomic) != 0)\
147
 
        PR_ASSERT(0);
148
 
 
149
 
        return rv;
150
 
}
151
 
 
152
 
PRInt32
153
 
_MD_AtomicSet(PRInt32 *val, PRInt32 newval)
154
 
{
155
 
    PRInt32 rv;
156
 
    if (mutex_lock(&_solaris_atomic) != 0)
157
 
        PR_ASSERT(0);
158
 
 
159
 
    rv = *val;
160
 
    *val = newval;
161
 
 
162
 
    if (mutex_unlock(&_solaris_atomic) != 0)\
163
 
        PR_ASSERT(0);
164
 
 
165
 
        return rv;
166
 
}
167
 
#endif  /* _PR_HAVE_ATOMIC_OPS */
168
 
#endif  /* !defined(i386) */
169
 
 
170
 
#if defined(_PR_GLOBAL_THREADS_ONLY)
171
 
#include <signal.h>
172
 
#include <errno.h>
173
 
#include <fcntl.h>
174
 
#include <thread.h>
175
 
 
176
 
#include <sys/lwp.h>
177
 
#include <sys/procfs.h>
178
 
#include <sys/syscall.h>
179
 
extern int syscall();  /* not declared in sys/syscall.h */
180
 
 
181
 
static sigset_t old_mask;       /* store away original gc thread sigmask */
182
 
static PRIntn gcprio;           /* store away original gc thread priority */
183
 
 
184
 
THREAD_KEY_T threadid_key;
185
 
THREAD_KEY_T cpuid_key;
186
 
THREAD_KEY_T last_thread_key;
187
 
static sigset_t set, oldset;
188
 
 
189
 
static void
190
 
threadid_key_destructor(void *value)
191
 
{
192
 
    PRThread *me = (PRThread *)value;
193
 
    PR_ASSERT(me != NULL);
194
 
    /* the thread could be PRIMORDIAL (thus not ATTACHED) */
195
 
    if (me->flags & _PR_ATTACHED) {
196
 
        /*
197
 
         * The Solaris thread library sets the thread specific
198
 
         * data (the current thread) to NULL before invoking
199
 
         * the destructor.  We need to restore it to prevent the
200
 
         * _PR_MD_CURRENT_THREAD() call in _PRI_DetachThread()
201
 
         * from attaching the thread again.
202
 
         */
203
 
        _PR_MD_SET_CURRENT_THREAD(me);
204
 
        _PRI_DetachThread();
205
 
    }
206
 
}
207
 
 
208
 
void _MD_EarlyInit(void)
209
 
{
210
 
    THR_KEYCREATE(&threadid_key, threadid_key_destructor);
211
 
    THR_KEYCREATE(&cpuid_key, NULL);
212
 
    THR_KEYCREATE(&last_thread_key, NULL);
213
 
    sigemptyset(&set);
214
 
    sigaddset(&set, SIGALRM);
215
 
}
216
 
 
217
 
PRStatus _MD_CreateThread(PRThread *thread, 
218
 
                                        void (*start)(void *), 
219
 
                                        PRThreadPriority priority,
220
 
                                        PRThreadScope scope, 
221
 
                                        PRThreadState state, 
222
 
                                        PRUint32 stackSize) 
223
 
{
224
 
        PRInt32 flags;
225
 
        
226
 
    /* mask out SIGALRM for native thread creation */
227
 
    thr_sigsetmask(SIG_BLOCK, &set, &oldset); 
228
 
 
229
 
    /*
230
 
     * Note that we create joinable threads with the THR_DETACHED
231
 
     * flag.  The reasons why we don't use thr_join to implement
232
 
     * PR_JoinThread are:
233
 
     * - We use a termination condition variable in the PRThread
234
 
     *   structure to implement PR_JoinThread across all classic
235
 
     *   nspr implementation strategies.
236
 
     * - The native threads may be recycled by NSPR to run other
237
 
     *   new NSPR threads, so the native threads may not terminate
238
 
     *   when the corresponding NSPR threads terminate.  
239
 
     */
240
 
    flags = THR_SUSPENDED|THR_DETACHED;
241
 
    if (_PR_IS_GCABLE_THREAD(thread) || (thread->flags & _PR_BOUND_THREAD) ||
242
 
                                                        (scope == PR_GLOBAL_BOUND_THREAD))
243
 
                flags |= THR_BOUND;
244
 
 
245
 
    if (thr_create(NULL, thread->stack->stackSize,
246
 
                  (void *(*)(void *)) start, (void *) thread, 
247
 
                                  flags,
248
 
                  &thread->md.handle)) {
249
 
        thr_sigsetmask(SIG_SETMASK, &oldset, NULL); 
250
 
        return PR_FAILURE;
251
 
    }
252
 
 
253
 
    /* When the thread starts running, then the lwpid is set to the right
254
 
     * value. Until then we want to mark this as 'uninit' so that
255
 
     * its register state is initialized properly for GC */
256
 
 
257
 
    thread->md.lwpid = -1;
258
 
    thr_sigsetmask(SIG_SETMASK, &oldset, NULL); 
259
 
    _MD_NEW_SEM(&thread->md.waiter_sem, 0);
260
 
 
261
 
    if ((scope == PR_GLOBAL_THREAD) || (scope == PR_GLOBAL_BOUND_THREAD)) {
262
 
                thread->flags |= _PR_GLOBAL_SCOPE;
263
 
    }
264
 
 
265
 
    _MD_SET_PRIORITY(&(thread->md), priority);
266
 
 
267
 
    /* Activate the thread */
268
 
    if (thr_continue( thread->md.handle ) ) {
269
 
        return PR_FAILURE;
270
 
    }
271
 
    return PR_SUCCESS;
272
 
}
273
 
 
274
 
void _MD_cleanup_thread(PRThread *thread)
275
 
{
276
 
    thread_t hdl;
277
 
 
278
 
    hdl = thread->md.handle;
279
 
 
280
 
    /* 
281
 
    ** First, suspend the thread (unless it's the active one)
282
 
    ** Because we suspend it first, we don't have to use LOCK_SCHEDULER to
283
 
    ** prevent both of us modifying the thread structure at the same time.
284
 
    */
285
 
    if ( thread != _PR_MD_CURRENT_THREAD() ) {
286
 
        thr_suspend(hdl);
287
 
    }
288
 
    PR_LOG(_pr_thread_lm, PR_LOG_MIN,
289
 
            ("(0X%x)[DestroyThread]\n", thread));
290
 
 
291
 
    _MD_DESTROY_SEM(&thread->md.waiter_sem);
292
 
}
293
 
 
294
 
void _MD_exit_thread(PRThread *thread)
295
 
{
296
 
    _MD_CLEAN_THREAD(thread);
297
 
    _MD_SET_CURRENT_THREAD(NULL);
298
 
}
299
 
 
300
 
void _MD_SET_PRIORITY(_MDThread *md_thread,
301
 
        PRThreadPriority newPri)
302
 
{
303
 
        PRIntn nativePri;
304
 
 
305
 
        if (newPri < PR_PRIORITY_FIRST) {
306
 
                newPri = PR_PRIORITY_FIRST;
307
 
        } else if (newPri > PR_PRIORITY_LAST) {
308
 
                newPri = PR_PRIORITY_LAST;
309
 
        }
310
 
        /* Solaris priorities are from 0 to 127 */
311
 
        nativePri = newPri * 127 / PR_PRIORITY_LAST;
312
 
        if(thr_setprio((thread_t)md_thread->handle, nativePri)) {
313
 
                PR_LOG(_pr_thread_lm, PR_LOG_MIN,
314
 
                   ("_PR_SetThreadPriority: can't set thread priority\n"));
315
 
        }
316
 
}
317
 
 
318
 
void _MD_WAIT_CV(
319
 
    struct _MDCVar *md_cv, struct _MDLock *md_lock, PRIntervalTime timeout)
320
 
{
321
 
    struct timespec tt;
322
 
    PRUint32 msec;
323
 
    PRThread *me = _PR_MD_CURRENT_THREAD();
324
 
 
325
 
        PR_ASSERT((!suspendAllOn) || (suspendAllThread != me));
326
 
 
327
 
    if (PR_INTERVAL_NO_TIMEOUT == timeout) {
328
 
        COND_WAIT(&md_cv->cv, &md_lock->lock);
329
 
    } else {
330
 
        msec = PR_IntervalToMilliseconds(timeout);
331
 
 
332
 
        GETTIME(&tt);
333
 
        tt.tv_sec += msec / PR_MSEC_PER_SEC;
334
 
        tt.tv_nsec += (msec % PR_MSEC_PER_SEC) * PR_NSEC_PER_MSEC;
335
 
        /* Check for nsec overflow - otherwise we'll get an EINVAL */
336
 
        if (tt.tv_nsec >= PR_NSEC_PER_SEC) {
337
 
            tt.tv_sec++;
338
 
            tt.tv_nsec -= PR_NSEC_PER_SEC;
339
 
        }
340
 
        COND_TIMEDWAIT(&md_cv->cv, &md_lock->lock, &tt);
341
 
    }
342
 
}
343
 
 
344
 
void _MD_lock(struct _MDLock *md_lock)
345
 
{
346
 
#ifdef DEBUG
347
 
    /* This code was used for GC testing to make sure that we didn't attempt
348
 
     * to grab any locks while threads are suspended.
349
 
     */
350
 
    PRLock *lock;
351
 
    
352
 
    if ((suspendAllOn) && (suspendAllThread == _PR_MD_CURRENT_THREAD())) {
353
 
        lock = ((PRLock *) ((char*) (md_lock) - offsetof(PRLock,ilock)));
354
 
        PR_ASSERT(lock->owner == NULL);
355
 
        return;
356
 
    }
357
 
#endif /* DEBUG */
358
 
 
359
 
    mutex_lock(&md_lock->lock);
360
 
}
361
 
 
362
 
PRThread *_pr_attached_thread_tls()
363
 
{
364
 
    PRThread *ret;
365
 
 
366
 
    thr_getspecific(threadid_key, (void **)&ret);
367
 
    return ret;
368
 
}
369
 
 
370
 
PRThread *_pr_current_thread_tls()
371
 
{
372
 
    PRThread *thread;
373
 
 
374
 
    thread = _MD_GET_ATTACHED_THREAD();
375
 
 
376
 
    if (NULL == thread) {
377
 
        thread = _PRI_AttachThread(
378
 
            PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
379
 
    }
380
 
    PR_ASSERT(thread != NULL);
381
 
 
382
 
    return thread;
383
 
}
384
 
 
385
 
PRStatus
386
 
_MD_wait(PRThread *thread, PRIntervalTime ticks)
387
 
{
388
 
        _MD_WAIT_SEM(&thread->md.waiter_sem);
389
 
        return PR_SUCCESS;
390
 
}
391
 
 
392
 
PRStatus
393
 
_MD_WakeupWaiter(PRThread *thread)
394
 
{
395
 
        if (thread == NULL) {
396
 
                return PR_SUCCESS;
397
 
        }
398
 
        _MD_POST_SEM(&thread->md.waiter_sem);
399
 
        return PR_SUCCESS;
400
 
}
401
 
 
402
 
_PRCPU *_pr_current_cpu_tls()
403
 
{
404
 
    _PRCPU *ret;
405
 
 
406
 
    thr_getspecific(cpuid_key, (void **)&ret);
407
 
    return ret;
408
 
}
409
 
 
410
 
PRThread *_pr_last_thread_tls()
411
 
{
412
 
    PRThread *ret;
413
 
 
414
 
    thr_getspecific(last_thread_key, (void **)&ret);
415
 
    return ret;
416
 
}
417
 
 
418
 
_MDLock _pr_ioq_lock;
419
 
 
420
 
void
421
 
_MD_InitIO(void)
422
 
{
423
 
    _MD_NEW_LOCK(&_pr_ioq_lock);
424
 
}
425
 
 
426
 
PRStatus _MD_InitializeThread(PRThread *thread)
427
 
{
428
 
    if (!_PR_IS_NATIVE_THREAD(thread))
429
 
        return PR_SUCCESS;
430
 
    /* sol_curthread is an asm routine which grabs GR7; GR7 stores an internal
431
 
     * thread structure ptr used by solaris.  We'll use this ptr later
432
 
     * with suspend/resume to find which threads are running on LWPs.
433
 
     */
434
 
    thread->md.threadID = sol_curthread();
435
 
                /* prime the sp; substract 4 so we don't hit the assert that
436
 
                 * curr sp > base_stack
437
 
                 */
438
 
    thread->md.sp = (uint_t) thread->stack->allocBase - sizeof(long);
439
 
    thread->md.lwpid = _lwp_self();
440
 
    thread->md.handle = THR_SELF();
441
 
 
442
 
        /* all threads on Solaris are global threads from NSPR's perspective
443
 
         * since all of them are mapped to Solaris threads.
444
 
         */
445
 
    thread->flags |= _PR_GLOBAL_SCOPE;
446
 
 
447
 
        /* For primordial/attached thread, we don't create an underlying native thread.
448
 
         * So, _MD_CREATE_THREAD() does not get called.  We need to do initialization
449
 
         * like allocating thread's synchronization variables and set the underlying
450
 
         * native thread's priority.
451
 
         */
452
 
        if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
453
 
            _MD_NEW_SEM(&thread->md.waiter_sem, 0);
454
 
            _MD_SET_PRIORITY(&(thread->md), thread->priority);
455
 
        }
456
 
        return PR_SUCCESS;
457
 
}
458
 
 
459
 
/* Sleep for n milliseconds, n < 1000   */
460
 
void solaris_msec_sleep(int n)
461
 
{
462
 
    struct timespec ts;
463
 
 
464
 
    ts.tv_sec = 0;
465
 
    ts.tv_nsec = 1000000*n;
466
 
    if (syscall(SYS_nanosleep, &ts, 0, 0) < 0) {
467
 
        PR_ASSERT(0);
468
 
    }
469
 
}      
470
 
 
471
 
#define VALID_SP(sp, bottom, top)   \
472
 
        (((uint_t)(sp)) > ((uint_t)(bottom)) && ((uint_t)(sp)) < ((uint_t)(top)))
473
 
 
474
 
void solaris_record_regs(PRThread *t, prstatus_t *lwpstatus)
475
 
{
476
 
#ifdef sparc
477
 
        long *regs = (long *)&t->md.context.uc_mcontext.gregs[0];
478
 
 
479
 
        PR_ASSERT(_PR_IS_GCABLE_THREAD(t));
480
 
        PR_ASSERT(t->md.threadID == lwpstatus->pr_reg[REG_G7]);
481
 
 
482
 
        t->md.sp = lwpstatus->pr_reg[REG_SP];
483
 
        PR_ASSERT(VALID_SP(t->md.sp, t->stack->stackBottom, t->stack->stackTop));
484
 
 
485
 
        regs[0] = lwpstatus->pr_reg[R_G1];
486
 
        regs[1] = lwpstatus->pr_reg[R_G2];
487
 
        regs[2] = lwpstatus->pr_reg[R_G3];
488
 
        regs[3] = lwpstatus->pr_reg[R_G4];
489
 
        regs[4] = lwpstatus->pr_reg[R_O0];
490
 
        regs[5] = lwpstatus->pr_reg[R_O1];
491
 
        regs[6] = lwpstatus->pr_reg[R_O2];
492
 
        regs[7] = lwpstatus->pr_reg[R_O3];
493
 
        regs[8] = lwpstatus->pr_reg[R_O4];
494
 
        regs[9] = lwpstatus->pr_reg[R_O5];
495
 
        regs[10] = lwpstatus->pr_reg[R_O6];
496
 
        regs[11] = lwpstatus->pr_reg[R_O7];
497
 
#elif defined(i386)
498
 
        /*
499
 
         * To be implemented and tested
500
 
         */
501
 
        PR_ASSERT(0);
502
 
        PR_ASSERT(t->md.threadID == lwpstatus->pr_reg[GS]);
503
 
        t->md.sp = lwpstatus->pr_reg[UESP];
504
 
#endif
505
 
}   
506
 
 
507
 
void solaris_preempt_off()
508
 
{
509
 
    sigset_t set;
510
 
 
511
 
    (void)sigfillset(&set);
512
 
    syscall(SYS_sigprocmask, SIG_SETMASK, &set, &old_mask);
513
 
}
514
 
 
515
 
void solaris_preempt_on()
516
 
{
517
 
    syscall(SYS_sigprocmask, SIG_SETMASK, &old_mask, NULL);      
518
 
}
519
 
 
520
 
int solaris_open_main_proc_fd()
521
 
{
522
 
    char buf[30];
523
 
    int fd;
524
 
 
525
 
    /* Not locked, so must be created while threads coming up */
526
 
    PR_snprintf(buf, sizeof(buf), "/proc/%ld", getpid());
527
 
    if ( (fd = syscall(SYS_open, buf, O_RDONLY)) < 0) {
528
 
        return -1;
529
 
    }
530
 
    return fd;
531
 
}
532
 
 
533
 
/* Return a file descriptor for the /proc entry corresponding to the
534
 
 * given lwp. 
535
 
 */
536
 
int solaris_open_lwp(lwpid_t id, int lwp_main_proc_fd)
537
 
{
538
 
    int result;
539
 
 
540
 
    if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCOPENLWP, &id)) <0)
541
 
        return -1; /* exited??? */
542
 
 
543
 
    return result;
544
 
}
545
 
void _MD_Begin_SuspendAll()
546
 
{
547
 
    solaris_preempt_off();
548
 
 
549
 
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin_SuspendAll\n"));
550
 
    /* run at highest prio so I cannot be preempted */
551
 
    thr_getprio(thr_self(), &gcprio);
552
 
    thr_setprio(thr_self(), 0x7fffffff); 
553
 
    suspendAllOn = PR_TRUE;
554
 
    suspendAllThread = _PR_MD_CURRENT_THREAD();
555
 
}
556
 
 
557
 
void _MD_End_SuspendAll()
558
 
{
559
 
}
560
 
 
561
 
void _MD_End_ResumeAll()
562
 
{
563
 
    PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End_ResumeAll\n"));
564
 
    thr_setprio(thr_self(), gcprio);
565
 
    solaris_preempt_on();
566
 
    suspendAllThread = NULL;
567
 
    suspendAllOn = PR_FALSE;
568
 
}
569
 
 
570
 
void _MD_Suspend(PRThread *thr)
571
 
{
572
 
   int lwp_fd, result;
573
 
   prstatus_t lwpstatus;
574
 
   int lwp_main_proc_fd = 0;
575
 
  
576
 
   if (!_PR_IS_GCABLE_THREAD(thr) || !suspendAllOn){
577
 
     /*XXX When the suspendAllOn is set, we will be trying to do lwp_suspend
578
 
      * during that time we can't call any thread lib or libc calls. Hence
579
 
      * make sure that no suspension is requested for Non gcable thread
580
 
      * during suspendAllOn */
581
 
      PR_ASSERT(!suspendAllOn);
582
 
      thr_suspend(thr->md.handle);
583
 
      return;
584
 
   }
585
 
 
586
 
    /* XXX Primordial thread can't be bound to an lwp, hence there is no
587
 
     * way we can assume that we can get the lwp status for primordial
588
 
     * thread reliably. Hence we skip this for primordial thread, hoping
589
 
     * that the SP is saved during lock and cond. wait. 
590
 
     * XXX - Again this is concern only for java interpreter, not for the
591
 
     * server, 'cause primordial thread in the server does not do java work
592
 
     */
593
 
    if (thr->flags & _PR_PRIMORDIAL)
594
 
      return;
595
 
    
596
 
    /* XXX Important Note: If the start function of a thread is not called,
597
 
     * lwpid is -1. Then, skip this thread. This thread will get caught
598
 
     * in PR_NativeRunThread before calling the start function, because
599
 
     * we hold the pr_activeLock during suspend/resume */
600
 
 
601
 
    /* if the thread is not started yet then don't do anything */
602
 
    if (!suspendAllOn || thr->md.lwpid == -1)
603
 
      return;
604
 
 
605
 
    if (_lwp_suspend(thr->md.lwpid) < 0) { 
606
 
       PR_ASSERT(0);
607
 
       return;
608
 
    }
609
 
 
610
 
    if ( (lwp_main_proc_fd = solaris_open_main_proc_fd()) < 0) {
611
 
        PR_ASSERT(0);
612
 
        return;   /* XXXMB ARGH, we're hosed! */
613
 
    }
614
 
 
615
 
   if ( (lwp_fd = solaris_open_lwp(thr->md.lwpid, lwp_main_proc_fd)) < 0) {
616
 
           PR_ASSERT(0);
617
 
           close(lwp_main_proc_fd);
618
 
           return;
619
 
   }
620
 
   if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) {
621
 
            /* Hopefully the thread just died... */
622
 
           close(lwp_fd);
623
 
           close(lwp_main_proc_fd);
624
 
           return;
625
 
   }
626
 
            while ( !(lwpstatus.pr_flags & PR_STOPPED) ) {
627
 
                if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) {
628
 
                    PR_ASSERT(0);  /* ARGH SOMETHING WRONG! */
629
 
                    break;
630
 
                }
631
 
                solaris_msec_sleep(1);
632
 
            }
633
 
            solaris_record_regs(thr, &lwpstatus);
634
 
            close(lwp_fd);
635
 
   close(lwp_main_proc_fd);
636
 
}
637
 
 
638
 
#ifdef OLD_CODE
639
 
 
640
 
void _MD_SuspendAll()
641
 
{
642
 
    /* On solaris there are threads, and there are LWPs. 
643
 
     * Calling _PR_DoSingleThread would freeze all of the threads bound to LWPs
644
 
     * but not necessarily stop all LWPs (for example if someone did
645
 
     * an attachthread of a thread which was not bound to an LWP).
646
 
     * So now go through all the LWPs for this process and freeze them.
647
 
     *
648
 
     * Note that if any thread which is capable of having the GC run on it must
649
 
     * had better be a LWP with a single bound thread on it.  Otherwise, this 
650
 
     * might not stop that thread from being run.
651
 
     */
652
 
    PRThread *current = _PR_MD_CURRENT_THREAD();
653
 
    prstatus_t status, lwpstatus;
654
 
    int result, index, lwp_fd;
655
 
    lwpid_t me = _lwp_self();
656
 
    int err;
657
 
    int lwp_main_proc_fd;
658
 
 
659
 
    solaris_preempt_off();
660
 
 
661
 
    /* run at highest prio so I cannot be preempted */
662
 
    thr_getprio(thr_self(), &gcprio);
663
 
    thr_setprio(thr_self(), 0x7fffffff); 
664
 
 
665
 
    current->md.sp = (uint_t)&me;       /* set my own stack pointer */
666
 
 
667
 
    if ( (lwp_main_proc_fd = solaris_open_main_proc_fd()) < 0) {
668
 
        PR_ASSERT(0);
669
 
        solaris_preempt_on();
670
 
        return;   /* XXXMB ARGH, we're hosed! */
671
 
    }
672
 
 
673
 
    if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCSTATUS, &status)) < 0) {
674
 
        err = errno;
675
 
        PR_ASSERT(0);
676
 
        goto failure;   /* XXXMB ARGH, we're hosed! */
677
 
    }
678
 
 
679
 
    num_lwps = status.pr_nlwp;
680
 
 
681
 
    if ( (all_lwps = (lwpid_t *)PR_MALLOC((num_lwps+1) * sizeof(lwpid_t)))==NULL) {
682
 
        PR_ASSERT(0);
683
 
        goto failure;   /* XXXMB ARGH, we're hosed! */
684
 
    }
685
 
           
686
 
    if ( (result = syscall(SYS_ioctl, lwp_main_proc_fd, PIOCLWPIDS, all_lwps)) < 0) {
687
 
        PR_ASSERT(0);
688
 
        PR_DELETE(all_lwps);
689
 
        goto failure;   /* XXXMB ARGH, we're hosed! */
690
 
    }
691
 
 
692
 
    for (index=0; index< num_lwps; index++) {
693
 
        if (all_lwps[index] != me)  {
694
 
            if (_lwp_suspend(all_lwps[index]) < 0) { 
695
 
                /* could happen if lwp exited */
696
 
                all_lwps[index] = me;   /* dummy it up */
697
 
            }
698
 
        }
699
 
    }
700
 
 
701
 
    /* Turns out that lwp_suspend is not a blocking call.
702
 
     * Go through the list and make sure they are all stopped.
703
 
     */
704
 
    for (index=0; index< num_lwps; index++) {
705
 
        if (all_lwps[index] != me)  {
706
 
            if ( (lwp_fd = solaris_open_lwp(all_lwps[index], lwp_main_proc_fd)) < 0) {
707
 
                PR_ASSERT(0);
708
 
                PR_DELETE(all_lwps);
709
 
                all_lwps = NULL;
710
 
                goto failure;   /* XXXMB ARGH, we're hosed! */
711
 
            }
712
 
 
713
 
            if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) {
714
 
                /* Hopefully the thread just died... */
715
 
                close(lwp_fd);
716
 
                continue;
717
 
            }
718
 
            while ( !(lwpstatus.pr_flags & PR_STOPPED) ) {
719
 
                if ( (result = syscall(SYS_ioctl, lwp_fd, PIOCSTATUS, &lwpstatus)) < 0) {
720
 
                    PR_ASSERT(0);  /* ARGH SOMETHING WRONG! */
721
 
                    break;
722
 
                }
723
 
                solaris_msec_sleep(1);
724
 
            }
725
 
            solaris_record_regs(&lwpstatus);
726
 
            close(lwp_fd);
727
 
        }
728
 
    }
729
 
 
730
 
    close(lwp_main_proc_fd);
731
 
 
732
 
    return;
733
 
failure:
734
 
    solaris_preempt_on();
735
 
    thr_setprio(thr_self(), gcprio);
736
 
    close(lwp_main_proc_fd);
737
 
    return;
738
 
}
739
 
 
740
 
void _MD_ResumeAll()
741
 
{
742
 
    int i;
743
 
    lwpid_t me = _lwp_self();
744
 
 
745
 
    for (i=0; i < num_lwps; i++) {
746
 
        if (all_lwps[i] == me)
747
 
            continue;
748
 
        if ( _lwp_continue(all_lwps[i]) < 0) {
749
 
            PR_ASSERT(0);  /* ARGH, we are hosed! */
750
 
        }
751
 
    }
752
 
 
753
 
    /* restore priority and sigmask */
754
 
    thr_setprio(thr_self(), gcprio);
755
 
    solaris_preempt_on();
756
 
    PR_DELETE(all_lwps);
757
 
    all_lwps = NULL;
758
 
}
759
 
#endif /* OLD_CODE */
760
 
 
761
 
#ifdef USE_SETJMP
762
 
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
763
 
{
764
 
    if (isCurrent) {
765
 
                (void) setjmp(CONTEXT(t));
766
 
    }
767
 
    *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
768
 
    return (PRWord *) CONTEXT(t);
769
 
}
770
 
#else
771
 
PRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np)
772
 
{
773
 
    if (isCurrent) {
774
 
                (void) getcontext(CONTEXT(t));
775
 
    }
776
 
    *np = NGREG;
777
 
    return (PRWord*) &t->md.context.uc_mcontext.gregs[0];
778
 
}
779
 
#endif  /* USE_SETJMP */
780
 
 
781
 
#else /* _PR_GLOBAL_THREADS_ONLY */
782
 
 
783
89
#if defined(_PR_LOCAL_THREADS_ONLY)
784
90
 
785
91
void _MD_EarlyInit(void)
860
166
 
861
167
#endif  /* _PR_LOCAL_THREADS_ONLY */
862
168
 
863
 
#endif /* _PR_GLOBAL_THREADS_ONLY */
864
 
 
865
169
#ifndef _PR_PTHREADS
866
170
#if defined(i386) && defined(SOLARIS2_4)
867
171
/*