/* TMMain.c, Copyright (c) by , Swiss Federal Institute of Technology, Computer Engineering and Networks Laboratory. TOPSY -- A Teachable Operating System. Implementation of a tiny and simple micro kernel for teaching purposes. For further information, please visit http://www.tik.ee.ethz.ch/~topsy This software is provided under the terms of the GNU General Public Licence. A full copy of the GNU GPL is provided in the file COPYING found in the development root of Topsy. */ /* File: $Source: /usr/drwho/vault/cvs/topsy/Topsy/Threads/TMMain.c,v $ Author(s): Affiliation: ETH Zuerich, TIK Version: $Revision: 1.31 $ Creation Date: Last Date of Change: $Date: 2000/03/31 17:50:40 $ by: $Author: gfa $ $Log: TMMain.c,v $ Revision 1.31 2000/03/31 17:50:40 gfa Merged with /Net from several term projects Revision 1.30 1999/12/13 21:48:33 ruf GNU General Public Licence Update Revision 1.29 1999/10/19 14:59:02 gfa *** empty log message *** Revision 1.28 1999/01/14 18:40:06 cjeker threadStart and threadBuild have now one more argument: priority Revision 1.27 1999/01/08 21:50:30 cjeker bug fix Revision 1.26 1999/01/07 16:15:55 cjeker removed lightWeight Threads and added new syscall tmGetIDInfo Revision 1.25 1999/01/06 17:47:35 cjeker code cleaning Revision 1.24 1998/06/05 14:36:06 gfa changes for tmInfo gettime Revision 1.23 1998/04/01 11:48:18 gfa changed "userThread" to "shell" Revision 1.22 1998/03/28 16:37:04 gfa removed warning 'could not send killreply'. this may fail if a thread kill's itself or a user tries to kill kernel threads. Revision 1.21 1998/03/26 20:36:23 gfa changed tmInfo dispatching for getFirst/getNext (parameter l) Revision 1.20 1997/04/13 16:59:09 conrad returning errorCode to UNKNOWN_SYSCALL instead of reply.id ... * Revision 1.19 1997/04/08 20:21:39 conrad * ignores TM_KILLREPLY messages * * Revision 1.18 1997/04/06 18:54:54 gfa * source cleanup and change to tmExit (added vmCleanup) * * Revision 1.17 1997/04/01 05:42:42 gfa * *** empty log message *** * * Revision 1.16 1997/03/31 20:36:07 gfa * *** empty log message *** * * Revision 1.15 1997/03/28 12:37:44 conrad * adding of TM_INFO * * Revision 1.14 1997/03/21 20:06:57 conrad * *** empty log message *** * * Revision 1.13 1997/03/21 20:01:53 conrad * new idle thread * * Revision 1.12 1997/03/21 17:24:25 conrad * cosmetics * * Revision 1.11 1997/03/19 21:38:08 conrad * cosmetics * * Revision 1.10 1997/03/16 22:13:06 gfa * *** empty log message *** * * Revision 1.9 1997/03/14 10:51:17 conrad * Adding of debug information * * Revision 1.8 1997/03/12 18:50:34 gfa * changed tmThreadStart to threadStart (no messages to one self) * * Revision 1.7 1997/03/12 17:53:48 conrad * Debugging version * * Revision 1.6 1997/03/09 20:43:41 gfa * *** empty log message *** * * Revision 1.5 1997/03/04 16:56:01 conrad * minor changes * * Revision 1.4 1997/02/25 16:58:14 conrad * better use of unions * * Revision 1.3 1997/02/21 16:52:29 conrad * very incomplete status due to major changes ... * * Revision 1.2 1997/02/21 09:15:13 conrad * Intermediate status (not yet completed) * * Revision 1.1 1997/02/12 15:35:07 conrad * Initial revision * * Revision 1.1 1997/02/04 11:43:36 topsy * Initial revision * */ #include "Syscall.h" #include "TMMain.h" #include "IOMain.h" #include "Memory.h" #include "TMThread.h" #include "TMScheduler.h" #include "TMTime.h" #include "HashList.h" /* Global variables */ HashList blockedThreadsOnRecvHashList; /* Module global variables */ ThreadId nextUserThreadId=FIRST_USERTHREAD; /* first user thread */ ThreadId nextKernelThreadId=FIRST_KERNELTHREAD; /* first reg. kernel thread */ void tmMain( ThreadArg userInitAddress) { ThreadId ioThreadId, initThreadId, newThreadId, idleThreadId; ThreadId fromId; Message message, reply; /* generic messages */ long int values[2]; /* Starting of a new thread for IO processing */ if ((ioThreadId = threadStart(ioMain, NULL, KERNEL, "ioThread", TMTHREADID, KERNEL_PRIORITY)) == TM_THREADSTARTFAILED) { PANIC("ioThread could not be started"); } /* Starting of the first user thread (code at userInitAddress) */ if ((initThreadId = threadStart( (ThreadMainFunction)userInitAddress, NULL, USER, "shell", TMTHREADID, USER_PRIORITY)) == TM_THREADSTARTFAILED) { PANIC("userThread could not be started"); } /* Starting a idle thread */ if ((idleThreadId = threadStart( (ThreadMainFunction)tmIdleMain, NULL, KERNEL, "idleThread", TMTHREADID, IDLE_PRIORITY)) == TM_THREADSTARTFAILED) { PANIC("idleThread could not be started"); } /* Entering main loop to process incoming messages */ while (TRUE) { fromId = ANY; tmMsgRecv( &fromId, ANYMSGTYPE, &message, INFINITY); switch (message.id) { case TM_START: if ( (newThreadId = /* Threads will be started with USER_PRIORITY for USER Mode or * * KERNEL_PRIORITY for KERNEL mode. THIS is NOT the right way(TM)! */ threadStart( message.msg.tmStart.fctnAddress, message.msg.tmStart.parameter, THREAD_MODE(message.from), message.msg.tmStart.name, message.from, THREAD_PRIORITY(message.from) ) ) == TM_THREADSTARTFAILED) { reply.msg.tmStartReply.errorCode = TM_STARTFAILED; } else { reply.msg.tmStartReply.errorCode = TM_STARTOK; reply.msg.tmStartReply.newId = newThreadId; } reply.id = TM_STARTREPLY; tmMsgSend(message.from, &reply); break; case TM_EXIT: threadExit(message.from); break; case TM_KILL: if ((threadKill( message.msg.tmKill.id, message.from)) == TM_THREADKILLFAILED) { reply.msg.tmKillReply.errorCode = TM_KILLFAILED; } else { reply.msg.tmKillReply.errorCode = TM_KILLOK; } reply.id = TM_KILLREPLY; tmMsgSend(message.from, &reply); break; case TM_KILLREPLY: /* simply digest Message (coming from oneself) */ break; case TM_INFO: if ((threadInfo( message.from, message.msg.tmInfo.about, message.msg.tmInfo.kind, message.msg.tmInfo.infoPtr, values)) != TM_OK) { reply.msg.tmInfoReply.errorCode = TM_INFOFAILED; } else { reply.msg.tmInfoReply.errorCode = TM_INFOOK; reply.msg.tmInfoReply.info[0] = values[0]; reply.msg.tmInfoReply.info[1] = values[1]; } reply.id = TM_INFOREPLY; tmMsgSend(message.from, &reply); break; case TM_GETTIME: if (tmTimeGet(& reply.msg.tmTime.seconds, & reply.msg.tmTime.microSeconds) != TM_OK) { reply.msg.tmTime.errorCode = TM_TIMEFAILED; } else { reply.msg.tmTime.errorCode = TM_TIMEOK; } reply.id = TM_GETTIMEREPLY; tmMsgSend(message.from, &reply); break; case TM_SETTIME: if (tmTimeSet(reply.msg.tmTime.seconds, reply.msg.tmTime.microSeconds) != TM_OK) { reply.msg.tmTime.errorCode = TM_TIMEFAILED; } else { reply.msg.tmTime.errorCode = TM_TIMEOK; } reply.id = TM_SETTIMEREPLY; tmMsgSend(message.from, &reply); break; #if 0 case TM_TIMERSET: errorCode = tmSetTimer( xxxxx ); if (errorCode == TIMER_FAILED) WARNING("tmSetTimer call failed\n"); break; case TM_TIMERLEFT: nLeft = tmLeftTimer( xxxxxxx ); reply.id = TM_TIMERLEFTREPLY; reply.msg.tmTimerLeftReply.n32Time = nLeft; reply.msg.tmTimerLeftReply.errorCode = TM_TIMERLEFTOK; if ((errorCode = tmMsgSend(message.from,&reply)) != TM_MSGSENDOK) { WARNING("tmTimerLeftReply could not be sent\n"); } break; case TM_TIMERCLEAR: nLeft = tmClearTimer( xxxxxxx ); if (nLeft == TIMER_FAILED) { reply.msg.tmTimerClearReply.errorCode = TM_TIMERCLEARFAILED; } else { reply.msg.tmTimerClearReply.errorCode = TM_TIMERCLEAROK; } reply.id = TM_TIMERCLEARREPLY; reply.msg.tmTimerClearReply.n32Time = nLeft; if ((errorCode = tmMsgSend(message.from,&reply)) != TM_MSGSENDOK) { WARNING("tmTimerClearReply could not be sent\n"); } break; // case TM_TIMERTICKS: same as gettime #endif default: /* Unknown system call received */ WARNING("thread manager: unknown message type received\n"); reply.id = UNKNOWN_SYSCALL; if ( ( tmMsgSend( message.from, &reply) ) != TM_MSGSENDOK ){ WARNING("syscallReply could not be sent\n"); } break; } } }