sync_md.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 564 行 · 第 1/2 页
C
564 行
long secs; long long tmp; gettimeofday(&tv, NULL); waitForever = CVM_FALSE; tmp = millis / 1000LL; secs = (long)tmp; if (secs != tmp) { /* overflow */ waitForever = CVM_TRUE; } else { timeout.tv_sec = tv.tv_sec + secs; timeout.tv_nsec = tv.tv_usec * 1000; timeout.tv_nsec += (millis % 1000) * 1000000; if (timeout.tv_nsec >= 1000000000) { ++timeout.tv_sec; timeout.tv_nsec -= 1000000000; } assert(timeout.tv_nsec < 1000000000); if (timeout.tv_sec < tv.tv_sec) { /* overflow */ waitForever = CVM_TRUE; } } } /* NOTE: The thing about Thread.interrupt() is that it is asynchronous with respect to Object.wait(). Hence, there is a race between when the interrupt request and when we actually enter into wait(). If the interrupt comes too early (i.e. we're not waiting yet), then we'll still end up waiting below. There's nothing wrong with this. */ if (self->interrupted) { self->interrupted = CVM_FALSE; return CVM_FALSE; } /* NOTE: For notify() and notifyAll(), the following variables and the enqueuing of this thread on the condvar's wait list are protected by synchronization on the mutex m. Thread.interrupt() will modify the value field asynchronously, but that does not have any negative side effects. */ self->notified = CVM_FALSE; self->isWaitBlocked = CVM_TRUE; self->value = 0; /* add ourself to the wait queue that notify and notifyAll look at */ enqueue(c, self); CVMmutexUnlock(m); /* notifies can happen now */ /* emulate semaphore wait */ pthread_mutex_lock(&self->wait_mutex); while (self->value == 0) { if (waitForever) { pthread_cond_wait(&self->wait_cv, &self->wait_mutex); } else { int status = pthread_cond_timedwait(&self->wait_cv, &self->wait_mutex, &timeout); if (status == ETIMEDOUT) { break; } } } pthread_mutex_unlock(&self->wait_mutex); self->isWaitBlocked = CVM_FALSE;#ifdef CVM_THREAD_SUSPENSION /* If we're supposed to be suspended, then suspend self: */ while (self->isSuspended) { suspendSelf(); }#endif /* CVM_THREAD_SUSPENSION */ /* reacquire condvar mutex */ CVMmutexLock(m); /* no more notifications after this point */ { /* find out why we were woken up */ if (self->notified) { /* normal notify or notifyAll */ assert(self->value == 1); /* removed from wait queue */ assert(self->next == NULL && self->prev_p == NULL); } else { /* * We were woken up by linuxSyncInterruptWait() posting on * the semaphore, or the timed wait timed out. */ assert(self->interrupted || !waitForever); dequeue_me(c, self); /* removed from wait queue */ assert(self->next == NULL && self->prev_p == NULL); } } /* * Workaround for Linux kernel bug exposed by LinuxThreads. */ setFPMode(); self->value = 0; if (self->interrupted) { self->interrupted = CVM_FALSE; return CVM_FALSE; } return CVM_TRUE;}/* emulate a semaphore post */#define SEM_POST(t) \do { \ pthread_mutex_lock(&(t)->wait_mutex); \ (t)->value = 1; \ pthread_cond_signal(&(t)->wait_cv); \ pthread_mutex_unlock(&(t)->wait_mutex); \} while (0)CVMBoolCVMcondvarInit(CVMCondVar * c, CVMMutex * m){ c->waiters = NULL; c->last_p = &c->waiters; return POSIXcondvarInit(&(c)->pcv, &(m)->pmtx);}voidCVMcondvarDestroy(CVMCondVar * c){ POSIXcondvarDestroy(&(c)->pcv);}voidCVMcondvarNotify(CVMCondVar * c){ CVMThreadID *t; if ((t = dequeue(c)) != NULL) { t->notified = CVM_TRUE; SEM_POST(t); }}voidCVMcondvarNotifyAll(CVMCondVar * c){ CVMThreadID *t; while ((t = dequeue(c)) != NULL) { t->notified = CVM_TRUE; SEM_POST(t); }}voidlinuxSyncInterruptWait(CVMThreadID *thread){ if (thread->isWaitBlocked) { /* thread->notified is not set */ /* thread will dequeue itself from wait queue */ SEM_POST(thread); }}#ifdef CVM_THREAD_SUSPENSIONvoidlinuxSyncSuspend(CVMThreadID *t){ /* The suspended flag can be modified asynchronously (last one to set its value get to say what it is. This is no different than racing suspend and resume requests. Last request (suspend or resume) determines if the target thread is suspended or not. NOTE: All the suspension magic is actually done by the target thread. The requestor doesn't get to check nor manipulate the state of the target thread. It only gets to make a request to suspend or resume the target thread. This allows us to avoid having to do some fancy synchronization between the requestor and the target thread when manipulating the target thread's state. */ t->isSuspended = CVM_TRUE; /* Tell the target thread to service the suspension: */ pthread_kill(POSIX_COOKIE(t), SIGUSR1);}voidlinuxSyncResume(CVMThreadID *t){ /* The suspended flag can be modified asynchronously (last one to set its value get to say what it is. This is no different than racing suspend and resume requests. Last request (suspend or resume) determines if the target thread is suspended or not. NOTE: All the suspension magic is actually done by the target thread. The requestor doesn't get to check nor manipulate the state of the target thread. It only gets to make a request to suspend or resume the target thread. This allows us to avoid having to do some fancy synchronization between the requestor and the target thread when manipulating the target thread's state. */ t->isSuspended = CVM_FALSE; /* Tell the target thread to service the suspension: */ pthread_kill(POSIX_COOKIE(t), SIGUSR1);}#endif /* CVM_THREAD_SUSPENSION *//* * Linux doesn't handle MT core dumps very well, so suspend here * for the debugger. */void crash(int sig){ int pid = getpid(); fprintf(stderr, "Process #%d received signal %d, suspending\n", pid, sig); kill(pid, SIGSTOP);}#if defined(CVM_JVMPI) || defined(CVM_JVMTI)void sigquitHandler(int sig){#ifdef CVM_JVMPI CVMjvmpiSetDataDumpRequested();#endif#ifdef CVM_JVMTI CVMjvmtiSetDataDumpRequested();#endif}#endifCVMBoollinuxSyncInit(void){ int result = 0; /* NOTE: handleSuspendResume() is needed regardless of whether we enable thread suspension or not. See notes on handleSuspendResume() above for details. */ { /* Signal initialization. The signals we recover from set the SA_RESTART flag. */ struct { int sig; void *handler; int flags; } const signals[] = {#if !defined(CVM_JIT) && !defined(CVM_USE_MEM_MGR) {SIGSEGV, crash, 0},#endif#if defined(CVM_JVMPI) || defined(CVM_JVMTI) {SIGQUIT, sigquitHandler, SA_RESTART},#endif {SIGUSR1, handleSuspendResume, SA_RESTART}, {SIGBUS, crash, 0}, {SIGILL, crash, 0}, {SIGFPE, crash, 0} }; int i; int numsignals = sizeof signals / sizeof signals[0]; for (i = 0; i < numsignals; ++i) { struct sigaction sa; sa.sa_handler = (void (*)(int))signals[i].handler; sa.sa_flags = signals[i].flags; sigemptyset(&sa.sa_mask); if ((result = sigaction(signals[i].sig, &sa, NULL)) == -1) break; } } return (result != -1);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?