⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sched.c

📁 快速开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * 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 the Netscape Portable Runtime library. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s):  Silicon Graphics, Inc. *  * Portions created by SGI are Copyright (C) 2000-2001 Silicon * Graphics, Inc.  All Rights Reserved. *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* * This file is derived directly from Netscape Communications Corporation, * and consists of extensive modifications made during the year(s) 1999-2000. */#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <time.h>#include <errno.h>#include "common.h"/* Global data */_st_vp_t _st_this_vp;           /* This VP */_st_thread_t *_st_this_thread;  /* Current thread */int _st_active_count = 0;       /* Active thread count */time_t _st_curr_time = 0;       /* Current time as returned by time(2) */st_utime_t _st_last_tset;       /* Last time it was fetched */int st_poll(struct pollfd *pds, int npds, st_utime_t timeout){  struct pollfd *pd;  struct pollfd *epd = pds + npds;  _st_pollq_t pq;  _st_thread_t *me = _ST_CURRENT_THREAD();  int n;  if (me->flags & _ST_FL_INTERRUPT) {    me->flags &= ~_ST_FL_INTERRUPT;    errno = EINTR;    return -1;  }  if ((*_st_eventsys->pollset_add)(pds, npds) < 0)    return -1;  pq.pds = pds;  pq.npds = npds;  pq.thread = me;  pq.on_ioq = 1;  _ST_ADD_IOQ(pq);  if (timeout != ST_UTIME_NO_TIMEOUT)    _ST_ADD_SLEEPQ(me, timeout);  me->state = _ST_ST_IO_WAIT;  _ST_SWITCH_CONTEXT(me);  n = 0;  if (pq.on_ioq) {    /* If we timed out, the pollq might still be on the ioq. Remove it */    _ST_DEL_IOQ(pq);    (*_st_eventsys->pollset_del)(pds, npds);  } else {    /* Count the number of ready descriptors */    for (pd = pds; pd < epd; pd++) {      if (pd->revents)	n++;    }  }  if (me->flags & _ST_FL_INTERRUPT) {    me->flags &= ~_ST_FL_INTERRUPT;    errno = EINTR;    return -1;  }  return n;}void _st_vp_schedule(void){  _st_thread_t *thread;  if (_ST_RUNQ.next != &_ST_RUNQ) {    /* Pull thread off of the run queue */    thread = _ST_THREAD_PTR(_ST_RUNQ.next);    _ST_DEL_RUNQ(thread);  } else {    /* If there are no threads to run, switch to the idle thread */    thread = _st_this_vp.idle_thread;  }  ST_ASSERT(thread->state == _ST_ST_RUNNABLE);  /* Resume the thread */  thread->state = _ST_ST_RUNNING;  _ST_RESTORE_CONTEXT(thread);}/* * Initialize this Virtual Processor */int st_init(void){  _st_thread_t *thread;  if (_st_active_count) {    /* Already initialized */    return 0;  }  /* We can ignore return value here */  st_set_eventsys(ST_EVENTSYS_DEFAULT);  if (_st_io_init() < 0)    return -1;  memset(&_st_this_vp, 0, sizeof(_st_vp_t));  ST_INIT_CLIST(&_ST_RUNQ);  ST_INIT_CLIST(&_ST_IOQ);  ST_INIT_CLIST(&_ST_ZOMBIEQ);#ifdef DEBUG  ST_INIT_CLIST(&_ST_THREADQ);#endif  if ((*_st_eventsys->init)() < 0)    return -1;  _st_this_vp.pagesize = getpagesize();  _st_this_vp.last_clock = st_utime();  /*   * Create idle thread   */  _st_this_vp.idle_thread = st_thread_create(_st_idle_thread_start,					     NULL, 0, 0);  if (!_st_this_vp.idle_thread)    return -1;  _st_this_vp.idle_thread->flags = _ST_FL_IDLE_THREAD;  _st_active_count--;  _ST_DEL_RUNQ(_st_this_vp.idle_thread);  /*   * Initialize primordial thread   */  thread = (_st_thread_t *) calloc(1, sizeof(_st_thread_t) +				   (ST_KEYS_MAX * sizeof(void *)));  if (!thread)    return -1;  thread->private_data = (void **) (thread + 1);  thread->state = _ST_ST_RUNNING;  thread->flags = _ST_FL_PRIMORDIAL;  _ST_SET_CURRENT_THREAD(thread);  _st_active_count++;#ifdef DEBUG  _ST_ADD_THREADQ(thread);#endif  return 0;}#ifdef ST_SWITCH_CBst_switch_cb_t st_set_switch_in_cb(st_switch_cb_t cb){  st_switch_cb_t ocb = _st_this_vp.switch_in_cb;  _st_this_vp.switch_in_cb = cb;  return ocb;}st_switch_cb_t st_set_switch_out_cb(st_switch_cb_t cb){  st_switch_cb_t ocb = _st_this_vp.switch_out_cb;  _st_this_vp.switch_out_cb = cb;  return ocb;}#endif/* * Start function for the idle thread *//* ARGSUSED */void *_st_idle_thread_start(void *arg){  _st_thread_t *me = _ST_CURRENT_THREAD();  while (_st_active_count > 0) {    /* Idle vp till I/O is ready or the smallest timeout expired */    _ST_VP_IDLE();    /* Check sleep queue for expired threads */    _st_vp_check_clock();    me->state = _ST_ST_RUNNABLE;    _ST_SWITCH_CONTEXT(me);  }  /* No more threads */  exit(0);  /* NOTREACHED */  return NULL;}void st_thread_exit(void *retval){  _st_thread_t *thread = _ST_CURRENT_THREAD();  thread->retval = retval;  _st_thread_cleanup(thread);  _st_active_count--;  if (thread->term) {    /* Put thread on the zombie queue */    thread->state = _ST_ST_ZOMBIE;    _ST_ADD_ZOMBIEQ(thread);    /* Notify on our termination condition variable */    st_cond_signal(thread->term);    /* Switch context and come back later */    _ST_SWITCH_CONTEXT(thread);    /* Continue the cleanup */    st_cond_destroy(thread->term);    thread->term = NULL;  }#ifdef DEBUG  _ST_DEL_THREADQ(thread);#endif  if (!(thread->flags & _ST_FL_PRIMORDIAL))    _st_stack_free(thread->stack);  /* Find another thread to run */  _ST_SWITCH_CONTEXT(thread);  /* Not going to land here */}int st_thread_join(_st_thread_t *thread, void **retvalp){  _st_cond_t *term = thread->term;  /* Can't join a non-joinable thread */  if (term == NULL) {    errno = EINVAL;    return -1;  }  if (_ST_CURRENT_THREAD() == thread) {    errno = EDEADLK;    return -1;  }  /* Multiple threads can't wait on the same joinable thread */  if (term->wait_q.next != &term->wait_q) {    errno = EINVAL;    return -1;  }  while (thread->state != _ST_ST_ZOMBIE) {    if (st_cond_timedwait(term, ST_UTIME_NO_TIMEOUT) != 0)      return -1;  }  if (retvalp)    *retvalp = thread->retval;  /*   * Remove target thread from the zombie queue and make it runnable.   * When it gets scheduled later, it will do the clean up.   */  thread->state = _ST_ST_RUNNABLE;  _ST_DEL_ZOMBIEQ(thread);  _ST_ADD_RUNQ(thread);  return 0;}void _st_thread_main(void){  _st_thread_t *thread = _ST_CURRENT_THREAD();  /*   * Cap the stack by zeroing out the saved return address register   * value. This allows some debugging/profiling tools to know when   * to stop unwinding the stack. It's a no-op on most platforms.   */  MD_CAP_STACK(&thread);  /* Run thread main */  thread->retval = (*thread->start)(thread->arg);  /* All done, time to go away */  st_thread_exit(thread->retval);}/* * Insert "thread" into the timeout heap, in the position * specified by thread->heap_index.  See docs/timeout_heap.txt * for details about the timeout heap.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -