Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/nsprpub/pr/src/threads/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quelle  prcthr.c   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "primpl.h"

#if defined(WIN95)
/*
** Some local variables report warnings on Win95 because the code paths
** using them are conditioned on HAVE_CUSTOME_USER_THREADS.
** The pragma suppresses the warning.
**
*/

#  pragma warning(disable : 4101)
#endif

extern PRLock* _pr_sleeplock; /* allocated and initialized in prinit */
/*
** Routines common to both native and user threads.
**
**
** Clean up a thread object, releasing all of the attached data. Do not
** free the object itself (it may not have been malloc'd)
*/

void _PR_CleanupThread(PRThread* thread) {
  /* Free up per-thread-data */
  _PR_DestroyThreadPrivate(thread);

  /* Free any thread dump procs */
  if (thread->dumpArg) {
    PR_DELETE(thread->dumpArg);
  }
  thread->dump = 0;

  PR_DELETE(thread->name);
  PR_DELETE(thread->errorString);
  thread->errorStringSize = 0;
  thread->errorStringLength = 0;
  thread->environment = NULL;
}

PR_IMPLEMENT(PRStatus) PR_Yield() {
  static PRBool warning = PR_TRUE;
  if (warning)
    warning = _PR_Obsolete("PR_Yield()""PR_Sleep(PR_INTERVAL_NO_WAIT)");
  return (PR_Sleep(PR_INTERVAL_NO_WAIT));
}

/*
** Make the current thread sleep until "timeout" ticks amount of time
** has expired. If "timeout" is PR_INTERVAL_NO_WAIT then the call is
** equivalent to a yield. Waiting for an infinite amount of time is
** allowed in the expectation that another thread will interrupt().
**
** A single lock is used for all threads calling sleep. Each caller
** does get its own condition variable since each is expected to have
** a unique 'timeout'.
*/

PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime timeout) {
  PRStatus rv = PR_SUCCESS;

  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }

  if (PR_INTERVAL_NO_WAIT == timeout) {
    /*
    ** This is a simple yield, nothing more, nothing less.
    */

    PRIntn is;
    PRThread* me = PR_GetCurrentThread();
    PRUintn pri = me->priority;
    _PRCPU* cpu = _PR_MD_CURRENT_CPU();

    if (_PR_IS_NATIVE_THREAD(me)) {
      _PR_MD_YIELD();
    } else {
      _PR_INTSOFF(is);
      _PR_RUNQ_LOCK(cpu);
      if (_PR_RUNQREADYMASK(cpu) >> pri) {
        me->cpu = cpu;
        me->state = _PR_RUNNABLE;
        _PR_ADD_RUNQ(me, cpu, pri);
        _PR_RUNQ_UNLOCK(cpu);

        PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: yielding"));
        _PR_MD_SWITCH_CONTEXT(me);
        PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: done"));

        _PR_FAST_INTSON(is);
      } else {
        _PR_RUNQ_UNLOCK(cpu);
        _PR_INTSON(is);
      }
    }
  } else {
    /*
    ** This is waiting for some finite period of time.
    ** A thread in this state is interruptible (PR_Interrupt()),
    ** but the lock and cvar used are local to the implementation
    ** and not visible to the caller, therefore not notifiable.
    */

    PRCondVar* cv;
    PRIntervalTime timein;

    timein = PR_IntervalNow();
    cv = PR_NewCondVar(_pr_sleeplock);
    PR_ASSERT(cv != NULL);
    PR_Lock(_pr_sleeplock);
    do {
      PRIntervalTime delta = PR_IntervalNow() - timein;
      if (delta > timeout) {
        break;
      }
      rv = PR_WaitCondVar(cv, timeout - delta);
    } while (rv == PR_SUCCESS);
    PR_Unlock(_pr_sleeplock);
    PR_DestroyCondVar(cv);
  }
  return rv;
}

PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread* thread) { return thread->id; }

PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread* thread) {
  return (PRThreadPriority)thread->priority;
}

PR_IMPLEMENT(PRThread*) PR_GetCurrentThread() {
  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }
  return _PR_MD_CURRENT_THREAD();
}

/*
** Set the interrupt flag for a thread. The thread will be unable to
** block in i/o functions when this happens. Also, any PR_Wait's in
** progress will be undone. The interrupt remains in force until
** PR_ClearInterrupt is called.
*/

PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread* thread) {
#ifdef _PR_GLOBAL_THREADS_ONLY
  PRCondVar* victim;

  _PR_THREAD_LOCK(thread);
  thread->flags |= _PR_INTERRUPT;
  victim = thread->wait.cvar;
  _PR_THREAD_UNLOCK(thread);
  if ((NULL != victim) && (!(thread->flags & _PR_INTERRUPT_BLOCKED))) {
    int haveLock = (victim->lock->owner == _PR_MD_CURRENT_THREAD());

    if (!haveLock) {
      PR_Lock(victim->lock);
    }
    PR_NotifyAllCondVar(victim);
    if (!haveLock) {
      PR_Unlock(victim->lock);
    }
  }
  return PR_SUCCESS;
#else /* ! _PR_GLOBAL_THREADS_ONLY */
  PRIntn is;
  PRThread* me = _PR_MD_CURRENT_THREAD();

  if (!_PR_IS_NATIVE_THREAD(me)) {
    _PR_INTSOFF(is);
  }

  _PR_THREAD_LOCK(thread);
  thread->flags |= _PR_INTERRUPT;
  switch (thread->state) {
    case _PR_COND_WAIT:
      /*
       * call is made with thread locked;
       * on return lock is released
       */

      if (!(thread->flags & _PR_INTERRUPT_BLOCKED)) {
        _PR_NotifyLockedThread(thread);
      }
      break;
    case _PR_IO_WAIT:
      /*
       * Need to hold the thread lock when calling
       * _PR_Unblock_IO_Wait().  On return lock is
       * released.
       */

#  if defined(XP_UNIX) || defined(WINNT)
      if (!(thread->flags & _PR_INTERRUPT_BLOCKED)) {
        _PR_Unblock_IO_Wait(thread);
      }
#  else
      _PR_THREAD_UNLOCK(thread);
#  endif
      break;
    case _PR_RUNNING:
    case _PR_RUNNABLE:
    case _PR_LOCK_WAIT:
    default:
      _PR_THREAD_UNLOCK(thread);
      break;
  }
  if (!_PR_IS_NATIVE_THREAD(me)) {
    _PR_INTSON(is);
  }
  return PR_SUCCESS;
#endif /* _PR_GLOBAL_THREADS_ONLY */
}

/*
** Clear the interrupt flag for self.
*/

PR_IMPLEMENT(void) PR_ClearInterrupt() {
  PRIntn is;
  PRThread* me = _PR_MD_CURRENT_THREAD();

  if (!_PR_IS_NATIVE_THREAD(me)) {
    _PR_INTSOFF(is);
  }
  _PR_THREAD_LOCK(me);
  me->flags &= ~_PR_INTERRUPT;
  _PR_THREAD_UNLOCK(me);
  if (!_PR_IS_NATIVE_THREAD(me)) {
    _PR_INTSON(is);
  }
}

PR_IMPLEMENT(void) PR_BlockInterrupt() {
  PRIntn is;
  PRThread* me = _PR_MD_CURRENT_THREAD();

  if (!_PR_IS_NATIVE_THREAD(me)) {
    _PR_INTSOFF(is);
  }
  _PR_THREAD_LOCK(me);
  _PR_THREAD_BLOCK_INTERRUPT(me);
  _PR_THREAD_UNLOCK(me);
  if (!_PR_IS_NATIVE_THREAD(me)) {
    _PR_INTSON(is);
  }
/* PR_BlockInterrupt */

PR_IMPLEMENT(void) PR_UnblockInterrupt() {
  PRIntn is;
  PRThread* me = _PR_MD_CURRENT_THREAD();

  if (!_PR_IS_NATIVE_THREAD(me)) {
    _PR_INTSOFF(is);
  }
  _PR_THREAD_LOCK(me);
  _PR_THREAD_UNBLOCK_INTERRUPT(me);
  _PR_THREAD_UNLOCK(me);
  if (!_PR_IS_NATIVE_THREAD(me)) {
    _PR_INTSON(is);
  }
/* PR_UnblockInterrupt */

/*
** Return the thread stack pointer of the given thread.
*/

PR_IMPLEMENT(void*) PR_GetSP(PRThread* thread) {
  return (void*)_PR_MD_GET_SP(thread);
}

PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread* thread) {
  return thread->environment;
}

PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread* thread, void* env) {
  thread->environment = env;
}

PR_IMPLEMENT(PRInt32)
PR_GetThreadAffinityMask(PRThread* thread, PRUint32* mask) {
#ifdef HAVE_THREAD_AFFINITY
  return _PR_MD_GETTHREADAFFINITYMASK(thread, mask);
#else
  return 0;
#endif
}

PR_IMPLEMENT(PRInt32)
PR_SetThreadAffinityMask(PRThread* thread, PRUint32 mask) {
#ifdef HAVE_THREAD_AFFINITY
  return _PR_MD_SETTHREADAFFINITYMASK(thread, mask);
#else
  return 0;
#endif
}

/* This call is thread unsafe if another thread is calling SetConcurrency()
 */

PR_IMPLEMENT(PRInt32) PR_SetCPUAffinityMask(PRUint32 mask) {
#ifdef HAVE_THREAD_AFFINITY
  PRCList* qp;
  extern PRUint32 _pr_cpu_affinity_mask;

  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }

  _pr_cpu_affinity_mask = mask;

  qp = _PR_CPUQ().next;
  while (qp != &_PR_CPUQ()) {
    _PRCPU* cpu;

    cpu = _PR_CPU_PTR(qp);
    PR_SetThreadAffinityMask(cpu->thread, mask);

    qp = qp->next;
  }
#endif

  return 0;
}

PRUint32 _pr_recycleThreads = 0;
PR_IMPLEMENT(void) PR_SetThreadRecycleMode(PRUint32 count) {
  _pr_recycleThreads = count;
}

PR_IMPLEMENT(PRThread*)
PR_CreateThreadGCAble(PRThreadType type, void (*start)(void* arg), void* arg,
                      PRThreadPriority priority, PRThreadScope scope,
                      PRThreadState state, PRUint32 stackSize) {
  return _PR_CreateThread(type, start, arg, priority, scope, state, stackSize,
                          _PR_GCABLE_THREAD);
}

#ifdef SOLARIS
PR_IMPLEMENT(PRThread*)
PR_CreateThreadBound(PRThreadType type, void (*start)(void* arg), void* arg,
                     PRUintn priority, PRThreadScope scope, PRThreadState state,
                     PRUint32 stackSize) {
  return _PR_CreateThread(type, start, arg, priority, scope, state, stackSize,
                          _PR_BOUND_THREAD);
}
#endif

PR_IMPLEMENT(PRThread*)
PR_AttachThreadGCAble(PRThreadType type, PRThreadPriority priority,
                      PRThreadStack* stack) {
  /* $$$$ not sure how to finese this one */
  PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
  return NULL;
}

PR_IMPLEMENT(void) PR_SetThreadGCAble() {
  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }
  PR_Lock(_pr_activeLock);
  _PR_MD_CURRENT_THREAD()->flags |= _PR_GCABLE_THREAD;
  PR_Unlock(_pr_activeLock);
}

PR_IMPLEMENT(void) PR_ClearThreadGCAble() {
  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }
  PR_Lock(_pr_activeLock);
  _PR_MD_CURRENT_THREAD()->flags &= (~_PR_GCABLE_THREAD);
  PR_Unlock(_pr_activeLock);
}

PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread* thread) {
  if (!_pr_initialized) {
    _PR_ImplicitInitialization();
  }

  if (_PR_IS_NATIVE_THREAD(thread)) {
    return (thread->flags & _PR_BOUND_THREAD) ? PR_GLOBAL_BOUND_THREAD
                                              : PR_GLOBAL_THREAD;
  } else {
    return PR_LOCAL_THREAD;
  }
}

PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread* thread) {
  return (thread->flags & _PR_SYSTEM) ? PR_SYSTEM_THREAD : PR_USER_THREAD;
}

PR_IMPLEMENT(PRThreadState) PR_GetThreadState(const PRThread* thread) {
  return (NULL == thread->term) ? PR_UNJOINABLE_THREAD : PR_JOINABLE_THREAD;
/* PR_GetThreadState */

Messung V0.5
C=90 H=98 G=94

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.