📄 l4thread.c
字号:
/* * l4thread.c * Internal threading backend of Kaffe for DROPS * * Copyright (c) 2004, 2005 * TU Dresden, Operating System Group. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. * * written by Alexander Boettcher <ab764283@os.inf.tu-dresden.de> */#include <l4/sys/rt_sched.h> /* realtime extension */#include <l4/semaphore/semaphore.h>#include <l4/log/l4log.h>#include <l4/util/macros.h> /* l4util_idfmt, l4util_idstr */#include <l4/util/rdtsc.h> /* l4_rdtsc */#include "debug.h"#include "jthread.h"#include "l4thread.h"#include "gc.h"#ifdef REALTIME_EXTENSION#include <l4/dm_generic/types.h>#include <l4/dm_mem/dm_mem.h>#include <l4/dm_phys/dm_phys.h>#include <l4/sys/rt_sched.h>#include <l4/util/kip.h>#include "realtimethread.h"#endif__leaflet leaflet = { 0, 0, #ifdef REALTIME_EXTENSION 0, /* noheapthreadcount */ #endif -1, L4SEMAPHORE_INITIALIZER(1), L4SEMAPHORE_INITIALIZER(1), L4_INVALID_ID, 0, 0, 0, 0x05#ifdef REALTIME_EXTENSION ,L4_INVALID_ID ,NULL //handler to call if overrun situation ,0 //cost(wcet) overruns ,0 //deadline overruns#endif };#ifdef REALTIME_EXTENSIONstatic l4_uint32_t area;#define L4KAFFE_PERIODIC 0x2U#endifvolatile jthread_t live = 0;static volatile unsigned long sleepcount = 0;void _l4threads_suspendall(void);void _l4threads_resumepoint(void);void _l4threads_suspendall_c(void) NONRETURNING;void _l4threads_suspendall_c(void){ l4_msgdope_t result; if (sleepcount == leaflet.threadCount) { { l4_ipc_send(leaflet.gc, L4_IPC_SHORT_MSG, 0, //l4_umword_t snd_dword0, 0, //l4_umword_t snd_dword1, L4_IPC_NEVER, &result); } while (L4_IPC_ERROR(result) == L4_IPC_SECANCELED || L4_IPC_ERROR(result) == L4_IPC_SEABORTED); } while (1) l4thread_sleep_forever();} asm("_l4threads_suspendall: \n\t" "pushl $0x0 \n\t" /*space for return address*/ "pushfl \n\t" /*eflags 32 bit*/ "pushal \n\t" /*eax,ecx,edx,ebx,esp,ebp,esi,edi*/ "incl sleepcount \n\t" "jmp _l4threads_suspendall_c \n\t" "_l4threads_resumepoint: \n\t" // resume here, with ex_regs "popal \n\t" "popfl \n\t" "retl");/* * prevent all other threads from running */void jthread_suspendall(void){ l4_umword_t old_eflags; l4_umword_t dummy; l4_msgdope_t result; l4_threadid_t src; l4_threadid_t preempter = L4_INVALID_ID; l4_threadid_t pager = L4_INVALID_ID; jthread_t current = live; l4thread_t myself = l4thread_myself(); leaflet.gc = l4_myself();// LOG("suspendall"); /* * ex-regs all threads and save their state */ while (current) { /** * NoHeapRealtimeThreads will not be stopped */ if (current->daemon==0 && #ifdef REALTIME_EXTENSION current->threadtype != THREADTYPE_NOHEAPREAL && #endif !l4thread_equal(current->l4thread,myself)) { l4_thread_ex_regs(l4thread_l4_id(current->l4thread), (unsigned long)_l4threads_suspendall, (l4_umword_t)-1, &preempter, &pager, &old_eflags,¤t->eip,¤t->esp); } current = current -> next; } /* * Waiting for the notification IPC of the last stopped thread */ { l4_ipc_wait(&src, L4_IPC_SHORT_MSG, &dummy, &dummy, L4_IPC_NEVER,&result); }while(!l4_tasknum_equal(leaflet.gc, src) || L4_IPC_ERROR(result) == L4_IPC_RECANCELED || L4_IPC_ERROR(result) == L4_IPC_REABORTED);// LOG("suspendall-complete");}/* * restore threads */voidjthread_unsuspendall(void){ volatile unsigned long int * ret_addr; l4_umword_t old_eflags,dummy; l4_threadid_t preempter = L4_INVALID_ID; l4_threadid_t pager = L4_INVALID_ID; l4thread_t myself = l4thread_myself(); jthread_t current = live; while (current) { /** * NoHeapRealtimeThreads are never stopped and therefore they are not resumed */ if (current->daemon==0 && #ifdef REALTIME_EXTENSION current->threadtype != THREADTYPE_NOHEAPREAL && #endif !l4thread_equal(current->l4thread,myself)) { current->esp -= 0x04; /* stack address for the return address*/ ret_addr = (unsigned long int *)current->esp; /* replace place holder with the eip*/ *ret_addr = current->eip; l4_thread_ex_regs(l4thread_l4_id(current->l4thread), (unsigned long)_l4threads_resumepoint, current->esp-0x24, &preempter, &pager, &old_eflags, &dummy, &dummy); } current = current -> next; } sleepcount = 0;}bool jthread_detach_current_thread (void){ jthread_t current= jthread_current(); printf("detach ....\n"); KGC_rmRef((Collector *)leaflet.threadCollector, current); return true;}int jthread_extract_stack(jthread_t jtid, void **from, unsigned *len){ l4_umword_t esp,eip,eflags; l4_addr_t low,high; l4_threadid_t pager = L4_INVALID_ID; l4_threadid_t preempter = L4_INVALID_ID; if (l4thread_get_stack(jtid->l4thread,&low,&high)){ assert(!"l4thread_get_stack() problem!"); } else { l4_thread_ex_regs_flags(l4thread_l4_id(jtid->l4thread), (l4_umword_t)-1, (l4_umword_t)-1, &preempter, &pager, &eflags, &eip, &esp, L4_THREAD_EX_REGS_NO_CANCEL); *from = (void *)esp; *len = high - esp; } return (1);}/* * free a thread context */void jthread_destroy(jthread_t tid UNUSED){// leaflet->memCollector.deallocator(tid);}/* * iterate over all live threads */voidjthread_walkLiveThreads (void(*func)(jthread_t,void*), void *priv){ jthread_t next = live; while (next) { #ifdef REALTIME_EXTENSION if (next->threadtype != THREADTYPE_NOHEAPREAL) #endif func(next,priv); next = next->next; }}voidjthread_walkLiveThreads_r(void (*func)(jthread_t, void*), void *priv){ jthread_walkLiveThreads(func, priv);}#ifdef REALTIME_EXTENSION/* * set a function to be run when deadline, period or wcet is missed/overruned */void jthread_misshandler(void (*f)(jthread_t, unsigned), unsigned costoverrun, unsigned deadlineoverrun){ leaflet.misshandler = f; leaflet.wcetover = costoverrun; leaflet.deadover = deadlineoverrun;}/* * Handling of preemption IPC and notification of the Kaffe VM */static void jthread_preemption(l4_threadid_t thread, unsigned type){ jthread_t data = (jthread_t)l4thread_data_get(l4thread_id(thread), leaflet.datakey); if (leaflet.misshandler != NULL && data != NULL) leaflet.misshandler(data, type); else LOG("drop one preemption IPC"); } /** * preempter thread for each Java thread */static void NONRETURNING jthread_preempter(void * obj){ l4_rt_preemption_t dw; l4_threadid_t src; l4_msgdope_t result; int error; l4_threadid_t self = l4_myself(); l4thread_started(obj); while (1) { /* wait for request */ error = l4_ipc_wait(&src, L4_IPC_SHORT_MSG, &dw.lh.low, &dw.lh.high, L4_IPC_NEVER, &result); if (error == 0 && leaflet.misshandler != NULL) { if (l4_tasknum_equal(self, src)) { switch(dw.p.type){ case L4_RT_PREEMPT_TIMESLICE:// LOG("TimeSlice "l4util_idfmt"/%d", l4util_idstr(src), dw.p.id); jthread_preemption(src, leaflet.wcetover); break; case L4_RT_PREEMPT_DEADLINE:// LOG("DeadLine "l4util_idfmt, l4util_idstr(src)); jthread_preemption(src, leaflet.deadover); break; default: LOG("unknown preemption"); } } } }}#endif/* * Initialize the threading system. * */jthread_t jthread_init(int pre UNUSED, int maxpr, int minpr UNUSED, Collector *threadCollector, void (*_onthreadexit)(void*), void (*_onstop)(void) UNUSED, void (*_ondeadlock)(void) UNUSED){ volatile jthread_t athread; #ifdef REALTIME_EXTENSION l4_threadid_t pager = L4_INVALID_ID; l4_threadid_t preempter; l4_umword_t dummy; /* start the preempter thread */ leaflet.preempter = l4thread_l4_id( l4thread_create_long(L4THREAD_INVALID_ID, jthread_preempter, 0, L4THREAD_INVALID_SP, L4THREAD_DEFAULT_SIZE, //threadStackSize, leaflet.startPrio + maxpr, 0, L4THREAD_CREATE_SYNC)); #endif leaflet.threadCollector = threadCollector; leaflet.onthreadexit = _onthreadexit; /* function to call, if a thread dies*/ leaflet.daemonCount = 0; /* count of all daemon threads */ leaflet.threadCount = 1; /* count of all threads */ #ifdef REALTIME_EXTENSION leaflet.noheapthreadCount = 0; /* count of all NoHeapRealtime threads */ #endif athread = KGC_malloc(threadCollector, sizeof (*athread), KGC_ALLOC_THREADCTX); KGC_addRef(threadCollector, athread); athread->l4thread = l4thread_myself(); athread->prev = NULL; athread->next = NULL; athread->daemon = 0; // no daemon thread athread->interrupting = 0; #ifdef REALTIME_EXTENSION athread->status = 0; #endif assert(live == NULL); live = athread; /* allocate data key */ leaflet.datakey = l4thread_data_allocate_key(); if (leaflet.datakey < 0) assert(!"l4thread_data_allocate_key failed"); if (l4thread_data_set_current(leaflet.datakey,athread) < 0) assert(!"l4thread_data_set_current failed"); #ifdef REALTIME_EXTENSION /* set the preempter for the current thread */ preempter = leaflet.preempter;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -