#endif
#include <string.h>
-#if !defined(USE_PTHREADS) && !defined(USE_SOLARIS_THREADS)
-
-#ifdef AFS_OSF_ENV
-extern void *malloc(int size);
-extern void *realloc(void *ptr, int size);
-#endif
#ifndef AFS_ARM_LINUX20_ENV
#if defined(AFS_OSF_ENV) || defined(AFS_S390_LINUX20_ENV)
extern int PRE_Block; /* from preempt.c */
}
return (0);
}
-
-
-#ifdef notdef
-/*
- * Print the specific limit out
- */
-int
-plim(char *name, afs_int32 lc, uchar_t hard)
-{
- struct rlimit rlim;
- int lim;
-
- printf("%s \t", name);
- (void)getrlimit(lc, &rlim);
- lim = hard ? rlim.rlim_max : rlim.rlim_cur;
- if (lim == RLIM_INFINITY)
- printf("unlimited");
- printf("%d %s", lim / 1024, "kbytes");
- printf("\n");
-}
-#endif
#endif
#ifdef AFS_SUN5_ENV
}
#endif
-#else
-#ifdef USE_SOLARIS_THREADS
-#include <thread.h>
-#else
-#include "pthread.h"
-#endif
-#include <stdio.h>
-#include <assert.h>
-
-pthread_mutex_t lwp_mutex; /* Mutex to ensure mutual exclusion of all LWP threads */
-
-PROCESS lwp_process_list; /* List of LWP initiated threads */
-
-pthread_key_t lwp_process_key; /* Key associating lwp pid with thread */
-
-#define CHECK check(__LINE__);
-
-typedef struct event {
- struct event *next; /* next in hash chain */
- void *event; /* lwp event: an address */
- int refcount; /* Is it in use? */
- pthread_cond_t cond; /* Currently associated condition variable */
- int seq; /* Sequence number: this is incremented
- * by wakeup calls; wait will not return until
- * it changes */
-} event_t;
-
-#define HASHSIZE 127
-event_t *hashtable[HASHSIZE]; /* Hash table for events */
-#define hash(event) ((unsigned long) (event) % HASHSIZE);
-
-#if CMA_DEBUG || DEBUGF
-char *
-lwp_process_string(void)
-{
- static char id[200];
- PROCESS p;
- LWP_CurrentProcess(&p);
- sprintf(id, "PID %x <%s>", p, p->name);
- return id;
-}
-#endif
-
-void
-lwp_unimplemented(char *interface)
-{
- fprintf(stderr,
- "cmalwp: %s is not currently implemented: program aborted\n",
- interface);
- exit(1);
-}
-
-static void
-lwpabort(char *interface)
-{
- fprintf(stderr, "cmalwp: %s failed unexpectedly\n", interface);
- abort();
-}
-
-int
-LWP_QWait(void)
-{
- lwp_unimplemented("LWP_QWait");
-}
-
-int
-LWP_QSignal(int pid)
-{
- lwp_unimplemented("LWP_QSignal");
-}
-
-/* Allocate and initialize an LWP process handle. The associated pthread handle
- * must be added by the caller, and the structure threaded onto the LWP active
- * process list by lwp_thread_process */
-static PROCESS
-lwp_alloc_process(char *name, pthread_startroutine_t ep, pthread_addr_t arg)
-{
- PROCESS lp;
- lp = (PROCESS) malloc(sizeof(*lp));
- assert(lp);
- memset(lp, 0, sizeof(*lp));
- if (!name) {
- char temp[100];
- static procnum;
- sprintf(temp, "unnamed_process_%04d", ++procnum);
- name = (char *)malloc(strlen(temp) + 1);
- assert(name);
- strcpy(name, temp);
- }
- lp->name = name;
- lp->ep = ep;
- lp->arg = arg;
- return lp;
-}
-
-/* Thread the LWP process descriptor *lp onto the lwp active process list
- * and associate a back pointer to the process descriptor from the associated
- * thread */
-static
-lwp_thread_process(PROCESS lp)
-{
- lp->next = lwp_process_list;
- lwp_process_list = lp;
- if (pthread_setspecific(lwp_process_key, (pthread_addr_t) lp) != 0)
- assert(0);
-}
-
-/* The top-level routine used as entry point to explicitly created LWP
- * processes. This completes a few details of process creation left
- * out by LWP_CreateProcess and calls the user-specified entry point */
-static int
-lwp_top_level(pthread_addr_t argp)
-{
- PROCESS lp = (PROCESS) argp;
-
- MUTEX_ENTER(&lwp_mutex);
- lwp_thread_process(lp);
- (lp->ep) (lp->arg);
- MUTEX_EXIT(&lwp_mutex);
- /* Should cleanup state */
-}
-
-int
-LWP_CreateProcess(pthread_startroutine_t ep, int stacksize, int priority,
- void *parm, char *name, PROCESS * pid)
-{
- int status;
- pthread_attr_t attr;
- pthread_t handle;
- PROCESS lp;
-
-#ifndef LWP_NO_PRIORITIES
- if (!cmalwp_pri_inrange(priority))
- return LWP_EBADPRI;
-#endif
- if (pthread_attr_create(&attr))
- assert(0);
- if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
- assert(0);
- if (stacksize)
- if (pthread_attr_setstacksize(&attr, stacksize))
- assert(0);
-#ifndef BDE_THREADS
- (void)pthread_attr_setinheritsched(&attr, PTHREAD_DEFAULT_SCHED);
- (void)pthread_attr_setsched(&attr, SCHED_FIFO);
-#ifndef LWP_NO_PRIORITIES
- (void)pthread_attr_setprio(&attr, cmalwp_lwppri_to_cmapri(priority));
-#endif
-#endif
- lp = lwp_alloc_process(name, (pthread_startroutine_t) ep,
- (pthread_addr_t) parm);
-
- /* allow new thread to run if higher priority */
- MUTEX_EXIT(&lwp_mutex);
- /* process is only added to active list after first time it runs (it adds itself) */
- status =
- pthread_create(&lp->handle, attr,
- (pthread_startroutine_t) lwp_top_level,
- (pthread_addr_t) lp);
- if (pthread_attr_delete(&attr))
- assert(0);
- if (pthread_mutex_lock(&lwp_mutex))
- assert(0);
- if (status != 0) {
- free(lp);
- return LWP_ENOMEM;
- }
- if (pid)
- *pid = lp;
- return LWP_SUCCESS;
-}
-
-PROCESS
-LWP_ActiveProcess(void)
-{ /* returns pid of current process */
- PROCESS pid;
- if (pthread_getspecific(lwp_process_key, (pthread_addr_t *) & pid))
- assert(0);
- return pid;
-}
-
-int
-LWP_CurrentProcess(PROCESS * pid)
-{ /* get pid of current process */
- if (pthread_getspecific(lwp_process_key, (pthread_addr_t *) pid))
- assert(0);
- return LWP_SUCCESS;
-}
-
-int
-LWP_DestroyProcess(PROCESS pid)
-{ /* destroy a lightweight process */
- lwp_unimplemented("LWP_DestroyProcess");
-}
-
-int
-LWP_DispatchProcess(void)
-{ /* explicit voluntary preemption */
- MUTEX_EXIT(&lwp_mutex);
- pthread_yield();
- MUTEX_ENTER(&lwp_mutex);
- return LWP_SUCCESS;
-}
-
-static int
-lwp_process_key_destructor(void)
-{
-}
-
-int
-LWP_InitializeProcessSupport(int priority, PROCESS * pid)
-{
- static int initialized = 0;
- int status;
- static PROCESS lp;
- extern main;
- int state;
-
- if (initialized) {
- if (pid)
- *pid = lp;
- return LWP_SUCCESS;
- }
-#ifndef LWP_NO_PRIORITIES
- if (priority < 0 || priority > LWP_MAX_PRIORITY)
- return LWP_EBADPRI;
-#endif
-
- /* Create pthread key to associate LWP process descriptor with each
- * LWP-created thread */
- if (pthread_keycreate(&lwp_process_key, (pthread_destructor_t)
- lwp_process_key_destructor))
- assert(0);
-
- lp = lwp_alloc_process("main process", main, 0);
- lp->handle = pthread_self();
- lwp_thread_process(lp);
-#ifndef LWP_NO_PRIORITIES
- (void)pthread_setscheduler(pthread_self(), SCHED_FIFO,
- cmalwp_lwppri_to_cmapri(priority));
-
-#endif
- MUTEX_INIT(&lwp_mutex, "lwp", MUTEX_DEFAULT, 0);
- MUTEX_ENTER(&lwp_mutex);
- initialized = 1;
- if (pid)
- *pid = lp;
- return LWP_SUCCESS;
-}
-
-int
-LWP_TerminateProcessSupport(void)
-{ /* terminate all LWP support */
- lwp_unimplemented("LWP_TerminateProcessSupport");
-}
-
-/* Get and initialize event structure corresponding to lwp event (i.e. address) */
-static event_t *
-getevent(void *event)
-{
- event_t *evp, *newp;
- int hashcode;
-
- hashcode = hash(event);
- evp = hashtable[hashcode];
- newp = 0;
- while (evp) {
- if (evp->event == event) {
- evp->refcount++;
- return evp;
- }
- if (evp->refcount == 0)
- newp = evp;
- evp = evp->next;
- }
- if (!newp) {
- newp = (event_t *) malloc(sizeof(event_t));
- assert(newp);
- newp->next = hashtable[hashcode];
- hashtable[hashcode] = newp;
- if (pthread_cond_init(&newp->cond, ((pthread_condattr_t) 0)))
- assert(0);
- newp->seq = 0;
- }
- newp->event = event;
- newp->refcount = 1;
- return newp;
-}
-
-/* Release the specified event */
-#define relevent(evp) ((evp)->refcount--)
-
-int
-LWP_WaitProcess(void *event)
-{ /* wait on a single event */
- struct event *ev;
- int seq;
- debugf(("%s: wait process (%x)\n", lwp_process_string(), event));
- if (event == NULL)
- return LWP_EBADEVENT;
- ev = getevent(event);
- seq = ev->seq;
- while (seq == ev->seq) {
- if (pthread_cond_wait(&ev->cond, &lwp_mutex))
- assert(0);
- }
- debugf(("%s: Woken up (%x)\n", lwp_process_string(), event));
- relevent(ev);
- return LWP_SUCCESS;
-}
-
-int
-LWP_MwaitProcess(int wcount, char *evlist[])
-{ /* wait on m of n events */
- lwp_unimplemented("LWP_MWaitProcess");
-}
-
-int
-LWP_NoYieldSignal(void *event)
-{
- struct event *ev;
- debugf(("%s: no yield signal (%x)\n", lwp_process_string(), event));
- if (event == NULL)
- return LWP_EBADEVENT;
- ev = getevent(event);
- if (ev->refcount > 1) {
- ev->seq++;
- if (pthread_cond_broadcast(&ev->cond))
- assert(0);
- }
- relevent(ev);
- return LWP_SUCCESS;
-}
-
-int
-LWP_SignalProcess(void *event)
-{
- struct event *ev;
- debugf(("%s: signal process (%x)\n", lwp_process_string(), event));
- if (event == NULL)
- return LWP_EBADEVENT;
- ev = getevent(event);
- if (ev->refcount > 1) {
- ev->seq++;
- MUTEX_EXIT(&lwp_mutex);
- CV_BROADCAST(&ev->cond);
- pthread_yield();
- MUTEX_ENTER(&lwp_mutex);
- }
- relevent(ev);
- return LWP_SUCCESS;
-}
-
-int
-LWP_StackUsed(PROCESS pid, int *maxa, int *used)
-{
- lwp_unimplemented("LWP_StackUsed");
-}
-
-int
-LWP_NewRock(int Tag, char *Value)
-{
- lwp_unimplemented("LWP_NewRock");
-}
-
-int
-LWP_GetRock(int Tag, char **Value)
-{
- lwp_unimplemented("LWP_GetRock");
-}
-
-int
-LWP_GetProcessPriority(PROCESS pid, int *priority)
-{ /* returns process priority */
- lwp_unimplemented("LWP_GetProcessPriority");
-}
-
-#endif /* USE_PTHREADS */
#define LWP_ENOROCKS -15 /* all rocks are in use */
#define LWP_EBADROCK -16 /* the specified rock does not exist */
-# if defined(USE_PTHREADS) || defined(USE_SOLARIS_THREADS)
-# ifdef USE_SOLARIS_THREADS
-# include <thread.h>
-typedef int pthread_t;
-typedef void *pthread_addr_t;
-typedef void *pthread_condattr_t;
-typedef void (*pthread_destructor_t) (void *);
-typedef pthread_addr_t(*pthread_startroutine_t) (pthread_addr_t);
-#define pthread_mutex_lock mutex_lock
-#define pthread_mutex_unlock mutex_unlock
-#define pthread_getspecific thr_getspecific
-#define pthread_setspecific thr_setspecific
-#define pthread_yield thr_yield
-/*typedef mutex_t pthread_mutex_t;*/
-typedef thread_key_t pthread_key_t;
-typedef cond_t PTHREAD_COND, *pthread_cond_t;
-
-#define PTHREAD_DEFAULT_SCHED 1
-#define SCHED_FIFO 2
-#define MUTEX_FAST_NP 0
-#define PTHREAD_DEFAULT_STACK 65536 /* 64 K */
-#define PRI_OTHER_MIN 1
-#define PRI_OTHER_MAX 127
-#define PRI_OTHER_MID ((PRI_OTHER_MIN + PRI_OTHER_MAX)/2)
-#define DESTRUCTOR_TAB_CHUNK 20
-#define maskAllSignals(o) thr_sigsetmask(SIG_BLOCK,&pthread_allSignals,&o)
-#define restoreAllSignals(o) thr_sigsetmask(SIG_SETMASK,&o,NULL)
-
-typedef struct PTHREAD_MUTEX {
- int kind;
- pthread_t ownerId;
- mutex_t fastMutex;
- int timesInside;
-} PTHREAD_MUTEX, *pthread_mutex_t;
-
-
-typedef struct PTHREAD_ATTR {
- long stackSize;
- int prio;
-} PTHREAD_ATTR, *pthread_attr_t;
-
-typedef struct {
- void (*destructor) (void *);
- thread_key_t key;
-} dest_slot_t;
-
-typedef struct {
- int nentries; /* size allocated (in terms of number of slots) */
- int next_free; /* next free slot */
- dest_slot_t slot[1];
-} pthread_destructor_tab_t;
-define DTAB_SIZE(size) (sizeof(pthread_destructor_tab_t) +
- (size) * sizeof(dest_slot_t))
-# else
-# include "pthread.h"
-# endif
-# include <assert.h>
-
-#define LWP_MAX_PRIORITY 0
-#define LWP_NORMAL_PRIORITY 0
-#define LWP_NO_PRIORITIES
-/*
- * We define PROCESS as a pointer to this struct, rather than simply as
- * a pthread_t since some applications test for a process handle being
- * non-zero. This can't be done on a pthread_t.
- */
-typedef struct lwp_process {
- pthread_t handle; /* The pthreads handle */
- struct lwp_process *next; /* Next LWP process */
- char *name; /* LWP name of the process */
- pthread_startroutine_t ep; /* Process entry point */
- pthread_addr_t arg; /* Initial parameter */
-} *PROCESS;
-
-struct rock { /* to hide things associated with this LWP under */
- int tag; /* unique identifier for this rock */
- char *value; /* pointer to some arbitrary data structure */
-};
-
-#define MAXROCKS 4 /* max no. of rocks per LWP */
-
-#define DEBUGF 0
-
-# ifndef BDE_THREADS
-/*#define CMA_DEBUG 1*/
-# endif
-
-# ifdef CMA_DEBUG
-# define LWP_CHECKSTUFF(msg) lwp_checkstuff(msg)
-# else
-# define LWP_CHECKSTUFF(msg)
-# endif
-
-# if DEBUGF
-# define debugf(m) printf m
-# else
-# define debugf(m)
-# endif
-
-# define IOMGR_Poll() LWP_DispatchProcess()
-
-/*
- * These two macros can be used to enter/exit the LWP context in a CMA
- * program. They simply acquire/release the global LWP mutex .
- */
-extern pthread_mutex_t lwp_mutex;
-#define LWP_EXIT_LWP_CONTEXT() MUTEX_EXIT(&lwp_mutex)
-#define LWP_ENTER_LWP_CONTEXT() MUTEX_ENTER(&lwp_mutex)
-#else
#ifndef AFS_NT40_ENV
#define lwp_abort() abort()
#endif
LWP_CreateProcess((a), (b), (c), (d), (e), (f))
#endif
-#endif /* USE_PTHREADS */
-
/* iomgr.c */
extern fd_set *IOMGR_AllocFDSet(void);
extern int IOMGR_Select(int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds,