pspposix.c
来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 465 行
C
465 行
/*************************************************************************** * * * db.* * * open source database kernel * * * * Copyright (c) 2000 Centura Software Corporation. All rights reserved. * * * * Use of this software, whether in source code format, or in executable, * * binary object code form, is governed by the CENTURA OPEN SOURCE LICENSE * * which is fully described in the LICENSE.TXT file, included within this * * distribution of source code files. * * * * Except as provided herein, the contents of this file are subject to the * * Centura Open Source Public License Version 1.0 (the "License"); you may * * not use this file except in compliance with the License. A copy of the * * License will be provided to you by Club ITTIA. * * * * Software distributed under the License is distributed on an "AS IS" * * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * * License for the specific language governing rights and limitations * * under the License. * * * * The Original Code is db.linux version 1.0, released February 29, 2000. * * * * The Initial Developer of the Original Code is Centura Software * * Corporation. Portions created by Centura Software Corporation are * * Copyright (C) 1984-2000 Centura Software Corporation. All Rights * * Reserved. * * * * This file contains modifications to the Original Code made by ITTIA. * * This file may only be used in accordance with the ITTIA DB.* V.2 * * License Agreement which is available at WWW.ITTIA.COM. * * * **************************************************************************//* pspposix.c - Contains Posix specific functions */#include <signal.h>#ifndef ECOS#include <sys/time.h>#endif#include "psp.h"#include "pspint.h"#ifndef MILLISEC#define MILLISEC 1000#endif#ifndef MICROSEC#define MICROSEC 1000000#endif#ifndef NANOSEC#define NANOSEC 1000000000#endif#if defined(BSDI)#define ETIME ETIMEDOUT#endif#define PSP_SEM_ENTRY_SIZE 1024#define PSP_SEM_TABLE_SIZE 128typedef struct { pthread_mutex_t mutex; int id_set; pthread_t id;} PSP_MUTEX_ENTRY;typedef struct { pthread_cond_t cond; pthread_mutex_t mutex; short flag;} PSP_EVENT_ENTRY;typedef struct { union { PSP_MUTEX_ENTRY m; PSP_EVENT_ENTRY e; } obj; short type; short avail; struct PSP_SEM_TABLE_ *owner;} PSP_SEM_ENTRY;typedef struct PSP_SEM_TABLE_ { PSP_SEM_ENTRY *entry; short avail;} PSP_SEM_TABLE;static PSP_SEM_TABLE sem_table[PSP_SEM_TABLE_SIZE];static pthread_mutex_t semTabMutex = PTHREAD_MUTEX_INITIALIZER;static pthread_mutex_t globalMutex = PTHREAD_MUTEX_INITIALIZER;static void semDelete(PSP_SEM_ENTRY *);#define SEM_END -1#define SEM_INUSE -2/* ========================================================================== Initialize synchronization functions*/int psp_syncInit( void){ memset(sem_table, 0, sizeof(sem_table)); return PSP_OKAY;}/* ========================================================================== Shutdown synchronization functions*/void psp_syncShutdown( void){ int ii; int jj; PSP_SEM_TABLE *p; PSP_SEM_ENTRY *sem; for (ii = 0, p = sem_table; ii < PSP_SEM_TABLE_SIZE; ii++, p++) { if (p->entry) { sem = p->entry; for (jj = 0; jj < PSP_SEM_ENTRY_SIZE; jj++, sem++) { if (sem->avail == SEM_INUSE) semDelete(sem); } psp_freeMemory(p->entry, 0); } }}/* ========================================================================== Cleanup synchronization functions*/void psp_syncTerm( void){}/* ========================================================================== Create a synchronization object*/PSP_SEM psp_syncCreate( short type){ short avail; int ii; int jj; PSP_SEM_TABLE *p; PSP_SEM_ENTRY *sem = NULL; if (!psp_inited) return NULL; pthread_mutex_lock(&semTabMutex); for (ii = 0, p = sem_table; ii < PSP_SEM_TABLE_SIZE; ii++, p++) { if (!p->entry) { sem = psp_cGetMemory(sizeof(PSP_SEM_ENTRY) * PSP_SEM_ENTRY_SIZE, 0); for (jj = 0; jj < PSP_SEM_ENTRY_SIZE; jj++) { sem[jj].avail = jj + 1; sem[jj].owner = p; } sem[jj - 1].avail = SEM_END; p->entry = sem; p->avail = 0; } if ((avail = p->avail) != SEM_END) { sem = &p->entry[avail]; p->avail = sem->avail; sem->avail = SEM_INUSE; break; } } pthread_mutex_unlock(&semTabMutex); if (!sem) { /* TBD: Log error about insufficient number of semaphores */ printf("Insufficient number of semaphores\n"); return NO_PSP_SEM; } switch (sem->type = type) { case PSP_MUTEX_SEM: pthread_mutex_init(&sem->obj.m.mutex, NULL); sem->obj.m.id_set = 0; break; case PSP_EVENT_SEM: pthread_mutex_init(&sem->obj.e.mutex, NULL); pthread_cond_init(&sem->obj.e.cond, NULL); sem->obj.e.flag = 1; break; default: /* TBD: Log out error about invalid semaphore type */ printf("Invalid semaphore type\n"); return NO_PSP_SEM; } return sem;}static void semDelete( PSP_SEM_ENTRY *sem){ switch (sem->type) { case PSP_MUTEX_SEM: pthread_mutex_destroy(&sem->obj.m.mutex); break; case PSP_EVENT_SEM: pthread_mutex_destroy(&sem->obj.e.mutex); pthread_cond_destroy(&sem->obj.e.cond); break; default: break; }}/* ========================================================================== Delete a synchronization object*/void psp_syncDelete( PSP_SEM sem){ PSP_SEM_ENTRY *entry = (PSP_SEM_ENTRY *) sem; PSP_SEM_TABLE *owner = entry->owner; semDelete(entry); entry->type = PSP_UNDEF_SEM; pthread_mutex_lock(&semTabMutex); /* put semaphore entry on available semaphore list */ entry->avail = owner->avail; owner->avail = (short) (entry - owner->entry); pthread_mutex_unlock(&semTabMutex);}/* ========================================================================== Obtain exclusive access to a mutex*/void psp_syncEnterExcl( PSP_SEM sem){ PSP_MUTEX_ENTRY *m = &((PSP_SEM_ENTRY *) sem)->obj.m; if (((PSP_SEM_ENTRY *) sem)->type != PSP_MUTEX_SEM) { /* TBD: Log out error */ printf("Invalid mutex\n"); } if (m->id_set & pthread_equal(m->id, pthread_self())) return; pthread_mutex_lock(&m->mutex); m->id_set = 1; m->id = pthread_self();}/* ========================================================================== Release exclusive access to a mutex*/void psp_syncExitExcl( PSP_SEM sem){ PSP_MUTEX_ENTRY *m = &((PSP_SEM_ENTRY *) sem)->obj.m; if (((PSP_SEM_ENTRY *) sem)->type != PSP_MUTEX_SEM) { /* TBD: Log out error */ printf("Invalid mutex\n"); } m->id_set = 0; m->id = 0; pthread_mutex_unlock(&m->mutex);}/* ========================================================================== Wait for an event*/#if defined(ETIME)#define TIMEDOUT(rc) (rc == ETIMEDOUT || rc == ETIME)#else#define TIMEDOUT(rc) (rc == ETIMEDOUT)#endifshort psp_syncWait( PSP_SEM sem, long timeout){ PSP_EVENT_ENTRY *e = &((PSP_SEM_ENTRY *) sem)->obj.e; short *flag = &e->flag; int ret = 0; struct timespec tm; if (((PSP_SEM_ENTRY *) sem)->type != PSP_EVENT_SEM) { /* TBD: Log out error */ printf("Invalid mutex\n"); } pthread_mutex_lock(&e->mutex); while (!*flag && !TIMEDOUT(ret)) { if (timeout == PSP_INDEFINITE_WAIT) pthread_cond_wait(&e->cond, &e->mutex); else {#ifdef ECOS clock_gettime(CLOCK_REALTIME, &tm); tm.tv_sec += (timeout / MILLISEC); tm.tv_nsec += (timeout % MILLISEC) * (NANOSEC / MILLISEC);#else struct timeval tmval; gettimeofday(&tmval, NULL); tm.tv_sec = tmval.tv_sec + (timeout / MILLISEC); tm.tv_nsec = (timeout % MILLISEC) * (NANOSEC / MILLISEC) + tmval.tv_usec * (NANOSEC / MICROSEC);#endif if (tm.tv_nsec > NANOSEC) { tm.tv_sec += tm.tv_nsec / NANOSEC; tm.tv_nsec %= NANOSEC; } ret = pthread_cond_timedwait(&e->cond, &e->mutex, &tm);#if defined(HPUX) if ((ret == -1) && (errno == EAGAIN)) ret = ETIME;#endif } } pthread_mutex_unlock(&e->mutex); return (TIMEDOUT(ret) ? PSP_TIMEOUT : PSP_OKAY);}/* ========================================================================== Set an event to the unsignalled state*/void psp_syncStart( PSP_SEM sem){ if (((PSP_SEM_ENTRY *) sem)->type != PSP_EVENT_SEM) { /* TBD: Log out error */ printf("Invalid mutex\n"); } ((PSP_SEM_ENTRY *) sem)->obj.e.flag = 0;}/* ========================================================================== Set an event to the signalled state*/void psp_syncResume( PSP_SEM sem){ PSP_EVENT_ENTRY *e = &((PSP_SEM_ENTRY *) sem)->obj.e; if (((PSP_SEM_ENTRY *) sem)->type != PSP_EVENT_SEM) { /* TBD: Log out error */ printf("Invalid mutex\n"); } pthread_mutex_lock(&e->mutex); e->flag = 1; pthread_cond_broadcast(&e->cond); pthread_mutex_unlock(&e->mutex);}/* ========================================================================== Get exclusive access to the global mutex*/void psp_enterCritSec( void){ pthread_mutex_lock(&globalMutex);}/* ========================================================================== Release exclusive access to the global mutex*/void psp_exitCritSec( void){ pthread_mutex_unlock(&globalMutex);}/* ========================================================================== Create a thread*/short psp_threadBegin( void (*fcn)(void *), unsigned int stacksize, void *arg){ pthread_t tid; pthread_attr_t attr; int ret;#if defined(LINUX) sigset_t orgset; sigset_t newset;#endif if (!psp_inited) return PSP_FAILED; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);#if defined(LINUX) __sigemptyset(&newset); __sigaddset(&newset, SIGINT); __sigaddset(&newset, SIGTERM); __sigaddset(&newset, SIGCHLD); pthread_sigmask(SIG_BLOCK, &newset, &orgset);#else#if defined(AIX) if (stacksize && stacksize < PTHREAD_STACK_MIN) stacksize = PTHREAD_STACK_MIN;#endif pthread_attr_setstacksize(&attr, stacksize);#endif ret = pthread_create(&tid, &attr, (void *(*)(void *))fcn, arg);#if defined(LINUX) pthread_sigmask(SIG_SETMASK, &orgset, NULL);#endif pthread_attr_destroy(&attr); if (ret != 0) return PSP_FAILED; return (ret == 0) ? PSP_OKAY : PSP_FAILED;}/* ========================================================================== End a thread*/void psp_threadEnd( void){ pthread_exit(NULL);}/* ========================================================================== Return the id of the current thread*/psp_thread_t psp_threadId( void){ return pthread_self();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?