示例#1
0
void threadPark(Thread *self, int absolute, long long time) {
    /* If we have a permit use it and return immediately.
       No locking as we're the only one that can change the
       state at this point */
    if(self->park_state == PARK_PERMIT) {
        self->park_state = PARK_RUNNING;
        MBARRIER();
        return;
    } 

    /* Spin until we can get the park lock.  This avoids having
       to disable suspension around pthread_mutex_lock */
    while(pthread_mutex_trylock(&self->park_lock))
        sched_yield();

    /* A thread may have given us a permit while we were waiting
       for the lock or we may be running.  Reduce the state by
       one (PERMIT -> RUNNING, RUNNING -> BLOCKED) and wait if
       we're now blocked */

    if(--self->park_state == PARK_BLOCKED) {
        /* Really must disable suspension now as we're
           going to sleep */
        disableSuspend(self);

        if(time) {
            struct timespec ts;

            if(absolute)
                getTimeoutAbsolute(&ts, time, 0);
            else
                getTimeoutRelative(&ts, 0, time);

            self->state = TIMED_WAITING;
            pthread_cond_timedwait(&self->park_cv, &self->park_lock, &ts);

            /* On Linux/i386 systems using LinuxThreads, pthread_cond_timedwait
               is implemented using sigjmp/longjmp.  This resets the fpu
               control word back to 64-bit precision.  The macro is empty for
               sane platforms. */ 

            FPU_HACK;
        } else {
            self->state = WAITING;
            pthread_cond_wait(&self->park_cv, &self->park_lock);
        }
        
        /* If we were unparked park_state will have been updated,
           but not if the wait timed out.  Only update if it's
           blocked, to avoid losing a possible permit */
        if(self->park_state == PARK_BLOCKED)
            self->park_state = PARK_RUNNING;

        self->state = RUNNING;

        enableSuspend(self);
    }

    pthread_mutex_unlock(&self->park_lock);
}
示例#2
0
文件: inlining.c 项目: OPSF/uClinux
void rewriteLock(Thread *self) {
    /* Only disable/enable suspension (slow) if
       we have to block */
    if(!tryLockVMLock(rewrite_lock, self)) {
        disableSuspend(self);
        lockVMLock(rewrite_lock, self);
        enableSuspend(self);
    }
}
示例#3
0
void resetPeakThreadsCount() {
    Thread *self = threadSelf();

    /* Grab the thread lock to protect against
       concurrent update by threads starting/dying */
    disableSuspend(self);
    pthread_mutex_lock(&lock);
    peak_threads_count = threads_count;
    pthread_mutex_unlock(&lock);
    enableSuspend(self);
}
示例#4
0
void createJavaThread(Object *jThread, long long stack_size) {
    //ExecEnv *ee;
    Thread *thread;
    Thread *self = threadSelf();
    Object *vmthread = allocObject(vmthread_class);

    if(vmthread == NULL)
        return;

    disableSuspend(self);

    pthread_mutex_lock(&lock);
    if(INST_DATA(jThread)[vmthread_offset]) {
        pthread_mutex_unlock(&lock);
        enableSuspend(self);
        signalException(java_lang_IllegalThreadStateException, "thread already started");
        return;
    }

    //ee = (ExecEnv*)sysMalloc(sizeof(ExecEnv));
    thread = new Thread;
    //memset(ee, 0, sizeof(ExecEnv));

//     thread->ee = ee;
//     ee->thread = jThread;
    thread->thread = jThread;
    //    ee->stack_size = stack_size;


    INST_DATA(vmthread)[vmData_offset] = (uintptr_t)thread;
    INST_DATA(vmthread)[thread_offset] = (uintptr_t)jThread;
    INST_DATA(jThread)[vmthread_offset] = (uintptr_t)vmthread;

    pthread_mutex_unlock(&lock);

    if(pthread_create(&thread->tid, &attributes, threadStart, thread)) {
        INST_DATA(jThread)[vmthread_offset] = 0;
        //sysFree(ee);
        enableSuspend(self);
        signalException(java_lang_OutOfMemoryError, "can't create thread");
        return;
    }

    pthread_mutex_lock(&lock);

    /* Wait for thread to start */
    while(thread->state == 0)
        pthread_cond_wait(&cv, &lock);

    pthread_mutex_unlock(&lock);
    enableSuspend(self);
}
示例#5
0
void mainThreadWaitToExitVM() {
    Thread *self = threadSelf();
    TRACE("Waiting for %d non-daemon threads to exit\n", non_daemon_thrds);

    disableSuspend(self);
    pthread_mutex_lock(&exit_lock);

    self->state = WAITING;
    while(non_daemon_thrds)
        pthread_cond_wait(&exit_cv, &exit_lock);

    pthread_mutex_unlock(&exit_lock);
    enableSuspend(self);
}
示例#6
0
void monitorLock(Monitor *mon, Thread *self) {
    if(mon->owner == self)
        mon->count++;
    else {
        if(pthread_mutex_trylock(&mon->lock)) {
            disableSuspend(self);

            self->blocked_mon = mon;
            self->blocked_count++;
            self->state = BLOCKED;

            pthread_mutex_lock(&mon->lock);

            self->state = RUNNING;
            self->blocked_mon = NULL;

            enableSuspend(self);
        }
        mon->owner = self;
    }
}
示例#7
0
文件: lock.c 项目: conferno/jamvm
void monitorLock(Monitor *mon, Thread *self) {
    if(mon->owner == self)
        mon->count++;
    else {
        if(pthread_mutex_trylock(&mon->lock)) {
            disableSuspend(self);

            self->blocked_mon = mon;
            self->blocked_count++;
            classlibSetThreadState(self, BLOCKED);

            pthread_mutex_lock(&mon->lock);

            classlibSetThreadState(self, RUNNING);
            self->blocked_mon = NULL;

            enableSuspend(self);
        }
        mon->owner = self;
    }
}
示例#8
0
int monitorWait0(Monitor *mon, Thread *self, long long ms, int ns,
                 int blocked, int interruptible) {
    char timed = (ms != 0) || (ns != 0);
    char interrupted = FALSE;
    char timeout = FALSE;
    struct timespec ts;
    int old_count;

    /* Check we own the monitor */
    if(mon->owner != self)
        return FALSE;

    disableSuspend(self);

    /* Unlock the monitor.  As it could be recursively
       locked remember the recursion count */
    old_count = mon->count;
    mon->owner = NULL;
    mon->count = 0;

    /* Counter used in thin-lock deflation */
    mon->in_wait++;

    self->wait_mon = mon;

    if(timed) {
       getTimeoutRelative(&ts, ms, ns);
       self->state = TIMED_WAITING;
    } else
       self->state = blocked ? BLOCKED : WAITING;

    if(interruptible && self->interrupted)
        interrupted = TRUE;
    else {
        if(blocked) {
            self->blocked_mon = mon;
            self->blocked_count++;
        } else
            self->waited_count++;

        self->interrupting = FALSE;

        /* Add the thread onto the end of the wait set */
        waitSetAppend(mon, self);

        while(self->wait_next != NULL && !self->interrupting && !timeout)
            if(timed) {
                timeout = pthread_cond_timedwait(&self->wait_cv,
                              &mon->lock, &ts) == ETIMEDOUT;

                /* On Linux/i386 systems using LinuxThreads,
                   pthread_cond_timedwait is implemented using
                   sigjmp/longjmp.  This resets the fpu control
                   word back to 64-bit precision.  The macro is
                   empty for sane platforms. */ 

                FPU_HACK;
            } else
                pthread_cond_wait(&self->wait_cv, &mon->lock);
    }

    /* If we've been interrupted or timed-out, we will not have been
       removed from the wait set.  If we have, we must have been
       notified afterwards.  In this case, the notify has been lost,
       and we must signal another thread */

    if(self->interrupting || timeout) {
        /* An interrupt after a timeout remains pending */
        interrupted = interruptible && !timeout;

        if(self->wait_next != NULL)
            waitSetUnlinkThread(mon, self);
        else {
            /* Notify lost.  Signal another thread only if it
               was on the wait set at the time of the notify */
            if(mon->wait_set != NULL && mon->wait_set->wait_id <
                                                self->notify_id) {
                Thread *thread = waitSetSignalNext(mon);
                thread->notify_id = self->notify_id;
            }
        }
    }

    self->state = RUNNING;
    self->wait_mon = NULL;

    if(blocked)
        self->blocked_mon = NULL;

   /* Restore the monitor owner and recursion count */
    mon->count = old_count;
    mon->owner = self;
    mon->in_wait--;

    enableSuspend(self);

    if(interrupted) {
        self->interrupted = FALSE;
        signalException(java_lang_InterruptedException, NULL);
    }

    return TRUE;
}
示例#9
0
void detachThread(Thread *thread) {
    Object *group, *excep;
    //ExecEnv *ee = thread->ee;
    //Object *jThread = ee->thread;
    Object *jThread = thread->thread;
    Object *vmthread = (Object*)INST_DATA(jThread)[vmthread_offset];

    /* Get the thread's group */
    group = (Object *)INST_DATA(jThread)[group_offset];

    /* If there's an uncaught exception, call uncaughtException on the thread's
       exception handler, or the thread's group if this is unset */
    if((excep = exceptionOccurred())) {
        FieldBlock *fb = findField(thread_class, SYMBOL(exceptionHandler),
                                                 SYMBOL(sig_java_lang_Thread_UncaughtExceptionHandler));
        Object *thread_handler = fb == NULL ? NULL : (Object *)INST_DATA(jThread)[fb->offset];
        Object *handler = thread_handler == NULL ? group : thread_handler;

        MethodBlock *uncaught_exp = lookupMethod(handler->classobj, SYMBOL(uncaughtException),
                                                 SYMBOL(_java_lang_Thread_java_lang_Throwable__V));

        if(uncaught_exp) {
            clearException();
            DummyFrame dummy;
            executeMethod(&dummy, handler, uncaught_exp, jThread, excep);
        } else
            printException();
    }

    /* remove thread from thread group */
    DummyFrame dummy;
    executeMethod(&dummy, group, (CLASS_CB(group->classobj))->method_table[rmveThrd_mtbl_idx], jThread);

    /* set VMThread ref in Thread object to null - operations after this
       point will result in an IllegalThreadStateException */
    INST_DATA(jThread)[vmthread_offset] = 0;

    /* Remove thread from the ID map hash table */
    deleteThreadFromHash(thread);

    /* Disable suspend to protect lock operation */
    disableSuspend(thread);

    /* Grab global lock, and update thread structures protected by
       it (thread list, thread ID and number of daemon threads) */
    pthread_mutex_lock(&lock);

    /* remove from thread list... */
    if((thread->prev->next = thread->next))
        thread->next->prev = thread->prev;

    /* One less live thread */
    threads_count--;

    /* Recycle the thread's thread ID */
    freeThreadID(thread->id);

    /* Handle daemon thread status */
    if(!INST_DATA(jThread)[daemon_offset])
        non_daemon_thrds--;

    pthread_mutex_unlock(&lock);

    /* notify any threads waiting on VMThread object -
       these are joining this thread */
    objectLock(vmthread);
    objectNotifyAll(vmthread);
    objectUnlock(vmthread);

    /* It is safe to free the thread's ExecEnv and stack now as these are
       only used within the thread.  It is _not_ safe to free the native
       thread structure as another thread may be concurrently accessing it.
       However, they must have a reference to the VMThread -- therefore, it
       is safe to free during GC when the VMThread is determined to be no
       longer reachable. */
//    sysFree(ee->stack);
    //sysFree(ee);

    /* If no more daemon threads notify the main thread (which
       may be waiting to exit VM).  Note, this is not protected
       by lock, but main thread checks again */

    if(non_daemon_thrds == 0) {
        /* No need to bother with disabling suspension
         * around lock, as we're no longer on thread list */
        pthread_mutex_lock(&exit_lock);
        pthread_cond_signal(&exit_cv);
        pthread_mutex_unlock(&exit_lock);
    }

    TRACE("Thread 0x%x id: %d detached from VM\n", thread, thread->id);
}
示例#10
0
文件: lock.c 项目: webos21/xi
int monitorWait0(Monitor *mon, Thread *self, long long ms, int ns, int blocked,
		int interruptible) {
	char timed = (ms != 0) || (ns != 0);
	char interrupted = FALSE;
	char timeout = FALSE;
	int ts = 0;
	int old_count = 0;

	// Check we own the monitor
	if (mon->owner != self)
		return FALSE;

	disableSuspend(self);

	// Unlock the monitor.  As it could be recursively
	// locked remember the recursion count
	old_count = mon->count;
	mon->owner = NULL;
	mon->count = 0;

	// Counter used in thin-lock deflation
	mon->in_wait++;

	self->wait_mon = mon;

	if (timed) {
		ts = getTimeoutRelative(ms, ns);
		self->state = TIMED_WAITING;
	} else {
		self->state = blocked ? BLOCKED : WAITING;
	}

	if (interruptible && self->interrupted) {
		interrupted = TRUE;
	} else {
		if (blocked) {
			self->blocked_mon = mon;
			self->blocked_count++;
		} else {
			self->waited_count++;
		}

		self->interrupting = FALSE;

		// Add the thread onto the end of the wait set
		waitSetAppend(mon, self);

		while (self->wait_next != NULL && !self->interrupting && !timeout)
			if (timed) {
				timeout = xi_thread_cond_timedwait(&self->wait_cv, &mon->lock,
						ts) == XI_COND_RV_ERR_TIMEOUT;

				// On Linux/i386 systems using LinuxThreads,
				// pthread_cond_timedwait is implemented using
				// sigjmp/longjmp.  This resets the fpu control
				// word back to 64-bit precision.  The macro is
				// empty for sane platforms.
				FPU_HACK;
			} else {
				xi_thread_cond_wait(&self->wait_cv, &mon->lock);
			}
	}

	// If we've been interrupted or timed-out, we will not have been
	// removed from the wait set.  If we have, we must have been
	// notified afterwards.  In this case, the notify has been lost,
	// and we must signal another thread

	if (self->interrupting || timeout) {
		// An interrupt after a timeout remains pending
		interrupted = interruptible && !timeout;

		if (self->wait_next != NULL) {
			waitSetUnlinkThread(mon, self);
		} else {
			// Notify lost.  Signal another thread only if it
			// was on the wait set at the time of the notify
			if (mon->wait_set != NULL && mon->wait_set->wait_id
					< self->notify_id) {
				Thread *thread = waitSetSignalNext(mon);
				thread->notify_id = self->notify_id;
			}
		}
	}

	self->state = RUNNING;
	self->wait_mon = NULL;

	if (blocked) {
		self->blocked_mon = NULL;
	}

	// Restore the monitor owner and recursion count
	mon->count = old_count;
	mon->owner = self;
	mon->in_wait--;

	enableSuspend(self);

	if (interrupted) {
		self->interrupted = FALSE;
		signalException(java_lang_InterruptedException, NULL);
	}

	return TRUE;
}