/* Syscall.c, Copyright (c) by Eckart Zitzler, Christian Conrad, George Fankhauser, 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/Topsy/Syscall.c,v $ Author(s): Eckart Zitzler, Christian Conrad, George Fankhauser Affiliation: ETH Zuerich, TIK Version: $Revision: 1.33 $ Creation Date: Last Date of Change: $Date: 2000/04/03 17:45:31 $ by: $Author: gfa $ $Log: Syscall.c,v $ Revision 1.33 2000/04/03 17:45:31 gfa *** empty log message *** Revision 1.32 1999/12/13 21:48:37 ruf GNU General Public Licence Update Revision 1.31 1999/01/07 16:15:55 cjeker removed lightWeight Threads and added new syscall tmGetIDInfo Revision 1.30 1998/06/05 14:38:37 gfa changes for get/set time Revision 1.29 1998/03/26 20:34:37 gfa added tmGetFirst and tmGetNext Revision 1.28 1997/04/25 08:24:02 gfa corrected reply msg in ioClose * Revision 1.27 1997/04/20 17:18:11 gfa * ioClose continued * * Revision 1.26 1997/04/18 18:53:05 gfa * fixed wrong parameter type in ioClose * * Revision 1.25 1997/04/09 16:22:12 conrad * bug correction in tmStart() * * Revision 1.24 1997/04/08 20:18:35 conrad * awful bug due to cut & paste ... * * Revision 1.23 1997/04/08 13:04:47 conrad * Change of syscall tmStart() * * Revision 1.22 1997/04/07 13:55:12 conrad * use of genericSyscall for thread management syscalls * * Revision 1.21 1997/04/06 18:46:27 gfa * added vmCleanup syscall * * Revision 1.20 1997/03/28 12:08:46 gfa * added tmGetInfo syscall, types and constants * * Revision 1.19 1997/03/24 20:31:58 gfa * removed all traces of hmAlloc/Free... * * Revision 1.18 1997/03/22 14:30:12 conrad * locks replace msg for heap * * Revision 1.17 1997/03/21 10:18:54 conrad * initialisation of reply.id for io syscalls * * Revision 1.16 1997/03/19 22:50:08 gfa * removed warnings to make syscall usable by user code. * changed threadExit to while (msgSend != OK) ; to try again when * the exit message could not be sent to TMTHREAD * * Revision 1.15 1997/03/19 22:28:07 gfa * fixed wrong return to all io syscalls * * Revision 1.14 1997/03/16 22:13:26 gfa * *** empty log message *** * * Revision 1.13 1997/03/14 10:49:40 conrad * Adding of debug information (few) * * Revision 1.12 1997/03/13 23:57:40 gfa * *** empty log message *** * * Revision 1.11 1997/03/13 18:32:10 gfa * wrote vm/hm syscalls * * Revision 1.10 1997/03/12 18:53:15 gfa * *** empty log message *** * * Revision 1.9 1997/03/11 08:17:33 gfa * renamed km calls to hm... * * Revision 1.8 1997/03/09 20:51:55 gfa * *** empty log message *** * * Revision 1.7 1997/02/24 21:35:45 conrad * incomplete version * * Revision 1.6 1997/02/23 18:35:03 gfa * added io syscalls interface and implementation * * Revision 1.5 1997/02/21 16:54:02 conrad * very incomplete status due to major changes ... * * Revision 1.4 1997/02/21 14:13:26 conrad * Implementation of thread manager system calls * * Revision 1.3 1997/02/20 14:30:55 conrad * Removal of #ifdef ... that have nothing to do in .c files * * Revision 1.2 1997/02/13 15:49:14 conrad * First compilation/linking of complete environment (all modules) * * Revision 1.1 1997/02/13 15:06:36 conrad * Initial revision * * Revision 1.4 1997/02/13 07:49:33 conrad * Syscalls for thread management added * * Revision 1.3 1997/02/12 13:02:00 zitzler * kernel syscalls for memory management added * * Revision 1.2 1997/02/12 10:32:43 zitzler * memory manager syscalls only * * Revision 1.1 1997/02/04 11:46:04 topsy * Initial revision * */ #include "Topsy.h" #include "Messages.h" #include "Memory.h" #include "Threads.h" #include "IO.h" #include "Syscall.h" #define SyscallError MessageError /* generic syscall handling * this procedure is used for the regular syscalls but is also intended * for special messages sent to any server (drivers, user space servers) */ SyscallError genericSyscall(ThreadId to, Message* message, Message* reply) { if (tmMsgSend(to, message) != TM_MSGSENDOK) { return TM_MSGSENDFAILED; } tmMsgRecv(&to, reply->id, reply, INFINITY); return TM_MSGRECVOK; } /* memory management */ SyscallError vmAlloc(Address *addressPtr, unsigned long int size) { Message message, reply; message.id = VM_ALLOC; message.msg.vmAlloc.size = size; reply.id = VM_ALLOCREPLY; if (genericSyscall(MMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return VM_ALLOCFAILED; *addressPtr = reply.msg.vmAllocReply.address; return reply.msg.vmAllocReply.errorCode; } SyscallError vmFree(Address address) { Message message, reply; message.id = VM_FREE; message.msg.vmFree.address = address; reply.id = VM_FREEREPLY; if (genericSyscall(MMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return VM_FREEFAILED; return reply.msg.vmFreeReply.errorCode; } SyscallError vmMove(Address *addressPtr, ThreadId newOwner) { Message message, reply; message.id = VM_MOVE; message.msg.vmMove.address = *addressPtr; message.msg.vmMove.newOwner = newOwner; reply.id = VM_MOVEREPLY; if (genericSyscall(MMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return VM_MOVEFAILED; *addressPtr = reply.msg.vmMoveReply.address; return reply.msg.vmMoveReply.errorCode; } SyscallError vmProtect(Address startAddress, unsigned long int size, ProtectionMode pmode) { Message message, reply; message.id = VM_PROTECT; message.msg.vmProtect.startAddress = startAddress; message.msg.vmProtect.size = size; message.msg.vmProtect.pmode = pmode; reply.id = VM_PROTECTREPLY; if (genericSyscall(MMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return VM_PROTECTFAILED; return reply.msg.vmProtectReply.errorCode; } SyscallError vmCleanup(ThreadId threadId) { Message message; message.id = VM_CLEANUP; message.msg.vmCleanup.threadId = threadId; if (tmMsgSend(MMTHREADID, &message) != TM_MSGSENDOK) { return VM_CLEANUPFAILED; } return VM_CLEANUPOK; } /* thread management */ /* NOTE: tmMsgSend() and tmMsgRecv() are implemented in SyscallMsg.S */ SyscallError tmStart( ThreadId* id, ThreadMainFunction function, ThreadArg parameter, char *name) { Message message, reply; message.id = TM_START; message.msg.tmStart.fctnAddress = function; message.msg.tmStart.parameter = parameter; message.msg.tmStart.name = name; reply.id = TM_STARTREPLY; if (genericSyscall(TMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return TM_STARTFAILED; *id = reply.msg.tmStartReply.newId; return reply.msg.tmStartReply.errorCode; } SyscallError tmKill( ThreadId id) { Message message, reply; message.id = TM_KILL; message.msg.tmKill.id = id; reply.id = TM_KILLREPLY; if (genericSyscall(TMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return TM_KILLFAILED; return reply.msg.tmKillReply.errorCode; } void tmYield() { Message message; /* Building of a Message */ message.id = TM_YIELD; /* Sending of message */ if (tmMsgSend( TMTHREADID, &message) != TM_MSGSENDOK ) { } /* No reply is expected */ } void tmExit() { Message message; /* Building of a Message */ message.id = TM_EXIT; /* Sending of message */ while (tmMsgSend(TMTHREADID, &message) != TM_MSGSENDOK) { /* try until we succeed */ } /* No reply is expected (i.e. the sender does no longer exist) */ } SyscallError tmGetInfo(ThreadId about, ThreadId* tid, ThreadId* ptid) { Message message, reply; message.id = TM_INFO; message.msg.tmInfo.kind = SPECIFIC_ID ; message.msg.tmInfo.about = about; reply.id = TM_INFOREPLY; if (genericSyscall(TMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return TM_INFOFAILED; *tid = reply.msg.tmInfoReply.info[0]; *ptid = reply.msg.tmInfoReply.info[1]; return reply.msg.tmInfoReply.errorCode; } SyscallError tmGetFirst(ThreadInfo* info) { Message message, reply; message.id = TM_INFO; message.msg.tmInfo.kind = GETFIRST; message.msg.tmInfo.infoPtr = info; reply.id = TM_INFOREPLY; if (genericSyscall(TMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return TM_INFOFAILED; return reply.msg.tmInfoReply.errorCode; } SyscallError tmGetNext(ThreadInfo* info) { Message message, reply; message.id = TM_INFO; message.msg.tmInfo.kind = GETNEXT; message.msg.tmInfo.infoPtr = info; reply.id = TM_INFOREPLY; if (genericSyscall(TMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return TM_INFOFAILED; return reply.msg.tmInfoReply.errorCode; } SyscallError tmGetThreadByName(char* name, ThreadId* tid) { Message message, reply; message.id = TM_INFO ; message.msg.tmInfo.kind = THREAD_BY_NAME; message.msg.tmInfo.infoPtr = (ThreadInfo*)name; reply.id = TM_INFOREPLY; if (genericSyscall(TMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return TM_INFOFAILED; *tid = reply.msg.tmInfoReply.info[0]; return reply.msg.tmInfoReply.errorCode; } SyscallError tmGetIDInfo(ThreadId about, ThreadInfo* info) { Message message, reply; message.id = TM_INFO ; message.msg.tmInfo.about = about; message.msg.tmInfo.kind = GET_ID_INFO ; message.msg.tmInfo.infoPtr = info; reply.id = TM_INFOREPLY; if (genericSyscall(TMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return TM_INFOFAILED; return reply.msg.tmInfoReply.errorCode; } SyscallError tmGetTime(unsigned long* seconds, unsigned long* microSeconds) { Message message, reply; message.id = TM_GETTIME ; reply.id = TM_GETTIMEREPLY; if (genericSyscall(TMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return TM_TIMEFAILED; *seconds = reply.msg.tmTime.seconds; *microSeconds = reply.msg.tmTime.microSeconds; return reply.msg.tmTime.errorCode; } SyscallError tmSetTime(unsigned long seconds, unsigned long microSeconds) { Message message, reply; message.id = TM_SETTIME ; message.msg.tmTime.seconds = seconds; message.msg.tmTime.microSeconds = microSeconds; reply.id = TM_SETTIMEREPLY; if (genericSyscall(TMTHREADID, &message, &reply) == TM_MSGSENDFAILED) return TM_TIMEFAILED; return reply.msg.tmTime.errorCode; } /* io interface */ SyscallError ioOpen(int deviceNumber, ThreadId* id) { Message message, reply; message.id = IO_OPEN; message.msg.ioOpen.deviceNumber = deviceNumber; reply.id = IO_OPENREPLY; if (genericSyscall(IOTHREADID, &message, &reply) == TM_MSGSENDFAILED) return IO_OPENFAILED; *id = reply.msg.ioOpenReply.deviceThreadId; return reply.msg.ioOpenReply.errorCode; } SyscallError ioClose(ThreadId id) { Message message, reply; ThreadId any = ANY; message.id = IO_CLOSE; message.msg.ioClose.deviceThreadId = id; reply.id = IO_CLOSEREPLY; if (tmMsgSend(IOTHREADID, &message) != TM_MSGSENDOK) { return TM_MSGSENDFAILED; } /* ioCloseReply may come from a driver or a driver (that's why &any) */ tmMsgRecv(&any, reply.id, &reply, INFINITY); return TM_MSGRECVOK; return reply.msg.ioCloseReply.errorCode; } SyscallError ioRead(ThreadId id, char* buffer, unsigned long int* nOfBytes) { Message message, reply; message.id = IO_READ; message.msg.ioRead.buffer = buffer; message.msg.ioRead.size = *nOfBytes; reply.id = IO_READREPLY; if (genericSyscall(id, &message, &reply) == TM_MSGSENDFAILED) return IO_READFAILED; *nOfBytes = reply.msg.ioReadReply.bytesRead; return reply.msg.ioReadReply.errorCode; } SyscallError ioWrite(ThreadId id, char* buffer, unsigned long int* nOfBytes) { Message message, reply; message.id = IO_WRITE; message.msg.ioWrite.buffer = buffer; message.msg.ioWrite.size = *nOfBytes; reply.id = IO_WRITEREPLY; if (genericSyscall(id, &message, &reply) == TM_MSGSENDFAILED) return IO_WRITEFAILED; *nOfBytes = reply.msg.ioWriteReply.bytesWritten; return reply.msg.ioWriteReply.errorCode; } SyscallError ioInit(ThreadId id) { Message message, reply; message.id = IO_INIT; reply.id = IO_INITREPLY; if (genericSyscall(id, &message, &reply) == TM_MSGSENDFAILED) return IO_INITFAILED; return reply.msg.ioInitReply.errorCode; } SyscallError ioSubscribe(ThreadId id, ThreadId from) { Message message, reply; message.id = IO_SUBSCRIBE; reply.id = IO_SUBSCRIBEREPLY; if (genericSyscall(id, &message, &reply) == TM_MSGSENDFAILED) return IO_SUBSCRIBEFAILED; return reply.msg.ioInitReply.errorCode; } void ioGetAddr(ThreadId id, char *addr, int len) { Message message, reply; message.id = IO_GETADDR; reply.id = IO_GETADDRREPLY; if (genericSyscall(id, &message, &reply) == TM_MSGSENDFAILED) return; while(len-- > 0) addr[len]=reply.msg.ioGetAddrReply.addr[len]; }