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

📄 disp.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 1992-2000 the Florida State University   Distributed by the Florida State University under the terms of the   GNU Library General Public License.This file is part of Pthreads.Pthreads is free software; you can redistribute it and/ormodify it under the terms of the GNU Library General PublicLicense as published by the Free Software Foundation (version 2).Pthreads is distributed "AS IS" in the hope that it will beuseful, but WITHOUT ANY WARRANTY; without even the impliedwarranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU Library General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with Pthreads; see the file COPYING.  If not, writeto the Free Software Foundation, 675 Mass Ave, Cambridge,MA 02139, USA.Report problems and direct all questions to:  pthreads-bugs@ada.cs.fsu.edu  @(#)disp.c	3.14 11/8/00*/#include "internals.h"#include "setjmp.h"#include <fsu_pthread/debug.h>#include <asm-leon/sigcontext.h>static int old_stack_ptr;static threadctx_t stack_env;static int status;extern pthread_cond_t *new_cond[NNSIG];     /* cond for user handlers         */extern struct context_t *new_scp[NNSIG];    /* info for user handlers         *//* * SWITCH_TO_STACK - macro to switch stacks * CAUTION: Variables used across calls to this macro must be declared as static */#define SWITCH_TO_STACK(new_sp, val) \  { \    static int ret; \    PDEBUG(PDBG_STACK,"switch to stack 0x%x",new_sp); \    if (!(ret = thread_setjmp(stack_env, FALSE))) { \      ret = new_sp; \      old_stack_ptr = stack_env[THREAD_JB_SP]; \      stack_env[THREAD_JB_SP] = ret; \      thread_longjmp(stack_env, (int) val); \    } \    val = (pthread_t) ret; \  }#ifdef C_CONTEXT_SWITCH/* * Context switch (preemptive), now coded in C instead of assembly * * Do NOT compile with -O3 or more. This file contains several signal * handling routines which modify global data. Thus, the last optimization * which is safe is -O2! * * Notice that functions within ifdef _ASM are still not to be * compiled. The code of these functions simply serves as pseudo- * code to better understand the assembly code. * * Portability notes: * System calls to BSD routines have to be changed to SVR4. * Some system calls (e.g. sigprocmask) are redefined by Pthreads. * Thus, uses of sigsetmask cannot be replaced by sigprocmask * but rather have to be translated into direct syscall()'s. *//* * temporary stack for dispatcher, pthread_handle_many_process_signals, * N nested function calls by pthread_handle_many_process_signals, * a possible sigtramp and universal handler, plus 1 window spare *///KERNEL_STACK pthread_tempstack __attribute__((aligned(8)));int disable_dbg = 0;/*------------------------------------------------------------*//*  * pthread_sched - dispatcher * assumes SET_KERNEL_FLAG */void pthread_sched(){  static volatile pthread_t old, new;  pthread_t pthread_sched_new_signals();  PTRACEIN;  old = mac_pthread_self();#if defined(DEF_RR)  if (old->state & T_ASYNCTIMER) {    /*     * was: pthread_cancel_timed_sigwait(old, FALSE, RR_TIME, TRUE);     * optimized for speed; timer removed from queue by no syscalls     * to setitimer since we call timed_sigwait before switching contexts     */    timer_ent_t tmr;#ifdef STAND_ALONE    extern pthread_timer_q_t pthread_timer;#else    extern pthread_timer_q pthread_timer;#endif    for (tmr = pthread_timer.head; tmr; tmr = tmr->next[TIMER_QUEUE])      if (tmr->thread == old && (tmr->mode & DEF_RR))	break;    if (tmr) {      old->state &= ~T_ASYNCTIMER;      pthread_q_timer_deq(&pthread_timer, tmr);    }  }#endif  do {    if (old && old->state & T_RETURNED) {      SWITCH_TO_STACK(SA((int) pthread_tempstack_top) - SA(WINDOWSIZE), old);      disable_dbg = 1; /* limited stack */      if (old->state & T_DETACHED) {	free(old->stack_base);	free(old);      }      mac_pthread_self() = old = NO_PTHREAD;    }        if ((new = TAILQ_FIRST(&ready)) == NO_PTHREAD ||        pthread_signonemptyset(&new_signals)) {            mac_pthread_self() = new;      new = pthread_sched_new_signals(old, FALSE);    }  } while ((new = TAILQ_FIRST(&ready)) == NO_PTHREAD ||           pthread_signonemptyset(&new_signals));  mac_pthread_self() = new;  PT_REENT_SET(new);  #ifdef DEF_RR  if (new->attr.sched == SCHED_RR && !(new->state & T_ASYNCTIMER))    pthread_timed_sigwait(new, (struct timespec *) NULL, RR_TIME, NULL, new);#endif /* DEF_RR */  if (!pthread_not_called_from_sighandler(new->context[THREAD_JB_PC]))    SIGPROCMASK(SIG_BLOCK, &all_signals, (struct sigset_t *) NULL);  if (!disable_dbg) {    PDEBUG_HEADER(PDBG_SCHED);    PDEBUG_PTNAME(PDBG_SCHED,old);    PDEBUG_SIMPLECODE(PDBG_SCHED," -> ");    PDEBUG_PTNAME(PDBG_SCHED,new);    PDEBUG_SIMPLECODE(PDBG_SCHED,"[stack: 0x%x]\n", new->context[THREAD_JB_SP]);  }    mac_pthread_self() = new; /* paranoia ??? */  PT_REENT_SET(new);  RESTORE_CONTEXT(new);}/*------------------------------------------------------------*//* * pthread_sched_new_signals - handle signals which came in while inside * the kernel by switching over to the temporary stack */pthread_t pthread_sched_new_signals(p, masked)     pthread_t p;     int masked;{  static pthread_t old, new;  extern pthread_t pthread_handle_many_process_signals();  old = p;  if (masked && old && !pthread_not_called_from_sighandler(old->context[THREAD_JB_PC]))    SIGPROCMASK(SIG_UNBLOCK, &all_signals, (struct sigset_t *) NULL);      /*   * always flush windows before the stack is changed to preserve the proper   * linking of frame pointers   */  if (old)    SWITCH_TO_STACK(SA((int) pthread_tempstack_top) - SA(WINDOWSIZE), old);  new = pthread_handle_many_process_signals();  if (old)    SWITCH_TO_STACK(old_stack_ptr, new);  return(new);}/*------------------------------------------------------------*//* * pthread_sched_wrapper - * assumes the following actions before/after call: * PRE:  save errno(p); * POST: restore errno(p); */#ifdef C_CONTEXT_SWITCHvoid pthread_sched_wrapper(sig, code, p)int sig, code;pthread_t p;#else /* !C_CONTEXT_SWITCH */void pthread_sched_wrapper(sig, code)int sig, code;#endif /* !C_CONTEXT_SWITCH */{  void pthread_signal_sched();#ifdef C_CONTEXT_SWITCH  if (!SAVE_CONTEXT(p))#endif /* C_CONTEXT_SWITCH */    pthread_signal_sched(sig, code);}/*------------------------------------------------------------*//* * pthread_not_called_from_sighandler - * This routine must textually follow pthread_sched_wrapper!!! */int pthread_not_called_from_sighandler(addr)int addr;{  return(addr < (int) pthread_sched_wrapper ||         addr >= (int) pthread_not_called_from_sighandler);}/* * NOTICE: THE FOLLOWING C CODE IS ONLY TO ANNOTATE THE CORRESPONDING * ASSEMBLY CODE. THE C CODE DOES NOT COMPILE AND NEVER WILL! */#ifdef _ASM/*------------------------------------------------------------*//* * pthread_test_and_set - */int pthread_test_and_set(flag)int *flag;{  return(ldstub(flag));}/*------------------------------------------------------------*//* * pthread_get_sp - */char *pthread_get_sp(){  return(sp);}/*------------------------------------------------------------*//* * pthread_set_sp - */void pthread_set_sp(new_sp)char *new_sp;{  sp = new_sp;}/*------------------------------------------------------------*//* * pthread_get_fp - */char *pthread_get_fp(){  return(fp);}/*------------------------------------------------------------*//* * pthread_set_fp - */void pthread_set_fp(new_fp)char *new_fp;{  fp = new_fp;}/*------------------------------------------------------------*//* * pthread_ST_FLUSH_WINDOWS - */void pthread_ST_FLUSH_WINDOWS(){  ST_FLUSH_WINDOWS();}#endif /* _ASM *//*------------------------------------------------------------*//* * pthread_fake_call_wrapper_wrapper - */void pthread_fake_call_wrapper_wrapper(){  pthread_t p = mac_pthread_self();  int sig = p->sig;  sigset_t smask;  struct context_t scp;  int new_context = p->nscp == (struct context_t *) DIRECTED_AT_THREAD;  void pthread_fake_call_wrapper();  extern struct sigaction pthread_user_handler[];  PTRACEIN;  if (new_context) {#if defined(SCO5)    getcontext(&scp);#endif    pthread_sigcpyset2set(&scp.sc_mask, &p->mask);    scp.sc_sp = p->osp;#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined(__dos__)    scp.sc_fp = p->obp;#endif    scp.sc_pc = p->opc;    PDEBUG(PDBG_SIGNAL,"new_context: sp: 0x%x pc: 0x%x (%x,%x)",p->osp,p->opc,&p->osp,&p->opc);    PDEBUG(PDBG_SIGNAL,"new_context: sp: 0x%x pc: 0x%x (%x)",scp.sc_sp,scp.sc_pc,&scp);    PDEBUG(PDBG_SIGNAL,"new_context: errno %d",p->pt_reentp->_errno);  }  pthread_sigcpyset2set(&smask, &p->mask);  if (sig != -1) {    pthread_sigcpyset2set(&p->mask, &pthread_user_handler[sig].sa_mask);    sigaddset(&p->mask, sig);  }  pthread_fake_call_wrapper(/*user_handler   */ sig == (int) PTHREAD_CANCELED ? (void (*)()) pthread_exit: pthread_user_handler[sig].sa_handler,                            /*smask          */ &smask,                            /*sig            */ sig,                            /*infop          */ &p->sig_info[sig==(int) PTHREAD_CANCELED ? 0 : sig],                            /*scp            */ new_context ? &scp : p->nscp,                            /*restore_context*/ new_context,			    /*oscp           */ sig == (int) PTHREAD_CANCELED ? 0 : new_scp[sig],			    /*cond           */(sig != (int) PTHREAD_CANCELED && new_cond[sig] != NULL) ? new_cond[sig] : p->cond);  new_scp[sig] = NULL;  new_cond[sig] = NULL;}/*------------------------------------------------------------*//* * pthread_clear_kernel_flag_wrapper - after a fake call with modified pc in the * context structure, return though this wrapper which clears the kernel * flag before jumping into user code. */void pthread_clear_kernel_flag_wrapper(){  register pthread_t p = mac_pthread_self();  register int osp = p->osp;  register int opc = p->opc;#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined(__dos__)  register int obp = p->obp;#endif  CLEAR_KERNEL_FLAG;  p->context[THREAD_JB_SP] = osp;  p->context[THREAD_JB_PC] = opc;#if defined (__FreeBSD__) || defined (_M_UNIX) || defined(__linux__) || defined (__dos__)  p->context[THREAD_JB_BP] = obp;#endif  RESTORE_CONTEXT(p);}/*------------------------------------------------------------*//* * pthread_fake_call_wrapper - invoke a fake call on a thread's stack * fake_call already puts the address of a user-defined handler * in %i0, the signal mask (to be restored) in %i1, and a flag * restore_context in %i5 which indicates if the context has to be * copied back by the wrapper (o.w. it is done by UNIX). * It calls the user handler with parameters sig, infop, scp. * Notice that the address of the condition variable is * passed on stack if the signal came in during a conditional wait. * In this case, the conditional wait terminates and the mutex is relocked * before the user handler is called. This is only done once for * nested handlers by the innermost handler (see check for zero-value * of the condition variable). * Notice that oscp is passed on stack and is restored as p->nscp * upon return from the wrapper. * The errno is saved across the user handler call. * assumes SET_KERNEL_FLAG still set from context switch after pushing fake call */void pthread_fake_call_wrapper(user_handler, smask, sig, infop, scp,                               restore_context, oscp, cond)     void (*user_handler)();     sigset_t *smask;     int sig;     struct siginfo *infop;

⌨️ 快捷键说明

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