1 using System;
  2 using cmsx.machine;
  3 
  4 namespace cmsx.kernel
  5 {
  6     public const byte sys_exit = 0u;
  7     public const byte sys_wait = 1u;
  8     public const byte sys_fork = 2u;
  9     public const byte sys_exec = 3u;
 10     public const byte sys_kill = 4u;
 11     public const byte sys_create = 5u;
 12     public const byte sys_open = 6u;
 13     public const byte sys_close = 7u;
 14     public const byte sys_read = 8u;
 15     public const byte sys_write = 9u;
 16     public const byte sys_seek = 10u;
 17     public const byte sys_tell = 11u;
 18     public const byte sys_pool_end = 12u;
 19     public const byte sys_set_pool_end = 13u;
 20     public const byte sys_debug_break = 14u;
 21     public const byte sys_stack_trace = 15u;
 22     public const byte sys_throw = 16u;
 23     public const byte sys_catch = 17u;
 24     public const byte sys_resume = 18u;
 25     public const byte sys_get_system_error = 19u;
 26     public const byte sys_get_current_time_point = 20u;
 27     public const byte sys_sleep = 21u;
 28     public const byte sys_get_current_date = 22u;
 29     public const byte sys_get_current_date_time = 23u;
 30     public const byte sys_pow = 24u;
 31     public const byte sys_get_random_seed = 25u;
 32     public const byte sys_link = 26u;
 33     public const byte sys_unlink = 27u;
 34     public const byte sys_rename = 28u;
 35     public const byte sys_mkdir = 29u;
 36     public const byte sys_opendir = 30u;
 37     public const byte sys_readdir = 31u;
 38     public const byte sys_closedir = 32u;
 39     public const byte sys_getcwd = 33u;
 40     public const byte sys_chdir = 34u;
 41     public const byte sys_stat = 35u;
 42     public const byte sys_umask = 36u;
 43     public const byte sys_ioctl = 37u;
 44     public const byte sys_chmod = 38u;
 45     public const byte sys_chown = 39u;
 46     public const byte sys_utime = 40u;
 47     public const byte sys_getuid = 41u;
 48     public const byte sys_setuid = 42u;
 49     public const byte sys_getgid = 43u;
 50     public const byte sys_setgid = 44u;
 51     public const byte sys_getpid = 45u;
 52     public const byte sys_getpgid = 46u;
 53     public const byte sys_setpgid = 47u;
 54     public const byte sys_getfgpid = 48u;
 55     public const byte sys_setfgpid = 49u;
 56     public const byte sys_sync = 50u;
 57     public const byte sys_times = 51u;
 58     public const byte sys_get_host_name = 52u;
 59     public const byte sys_dup = 53u;
 60     public const byte sys_pipe = 54u;
 61     public const byte sys_log = 55u;
 62     public const byte sys_log_message = 56u;
 63     
 64     public const byte numSystemCalls = sys_log_message + 1u;
 65 
 66     public nothrow string SystemCallName(byte systemCall)
 67     {
 68         switch (systemCall)
 69         {
 70             case sys_exit: return "sys_exit";
 71             case sys_wait: return "sys_wait";
 72             case sys_fork: return "sys_fork";
 73             case sys_exec: return "sys_exec";
 74             case sys_kill: return "sys_kill";
 75             case sys_create: return "sys_create";
 76             case sys_open: return "sys_open";
 77             case sys_close: return "sys_close";
 78             case sys_read: return "sys_read";
 79             case sys_write: return "sys_write";
 80             case sys_seek: return "sys_seek";
 81             case sys_tell: return "sys_tell";
 82             case sys_pool_end:  return "sys_pool_end";
 83             case sys_set_pool_end: return "sys_set_pool_end";
 84             case sys_debug_break:  return "sys_debug_break";
 85             case sys_stack_trace: return "sys_stack_trace";
 86             case sys_throw: return "sys_throw";
 87             case sys_catch: return "sys_catch";
 88             case sys_resume: return "sys_resume";
 89             case sys_get_system_error: return "sys_get_system_error";
 90             case sys_get_current_time_point: return "sys_get_current_time_point";
 91             case sys_sleep: return "sys_sleep";
 92             case sys_get_current_date: return "sys_get_current_date";
 93             case sys_get_current_date_time: return "sys_get_current_date_time";
 94             case sys_pow: return "sys_pow";
 95             case sys_get_random_seed: return "sys_get_random_seed";
 96             case sys_link: return "sys_link";
 97             case sys_unlink: return "sys_unlink";
 98             case sys_rename: return "sys_rename";
 99             case sys_mkdir: return "sys_mkdir";
100             case sys_opendir: return "sys_opendir";
101             case sys_readdir: return "sys_readdir";
102             case sys_closedir: return "sys_closedir";
103             case sys_getcwd: return "sys_getcwd";
104             case sys_chdir: return "sys_chdir";
105             case sys_stat: return "sys_stat";
106             case sys_umask: return "sys_umask";
107             case sys_ioctl: return "sys_ioctl";
108             case sys_chmod: return "sys_chmod";
109             case sys_chown: return "sys_chown";
110             case sys_utime: return "sys_utime";
111             case sys_getuid: return "sys_getuid";
112             case sys_setuid: return "sys_setuid";
113             case sys_getgid: return "sys_getgid";
114             case sys_setgid: return "sys_setgid";
115             case sys_getpid: return "sys_getpid";
116             case sys_getpgid: return "sys_getpgid";
117             case sys_setpgid: return "sys_setpgid";
118             case sys_getfgpid: return "sys_getfgpid";
119             case sys_setfgpid: return "sys_setfgpid";
120             case sys_sync: return "sys_sync";
121             case sys_times: return "sys_times";
122             case sys_get_host_name: return "sys_get_host_name";
123             case sys_dup: return "sys_dup";
124             case sys_pipe: return "sys_pipe";
125             case sys_log: return "sys_log";
126             case sys_log_message: return "sys_log_message";
127         }
128         return string();
129     }
130 
131     public const uint debugBreakInst = (TRAP << 24u) | (0u << 16u) | (sys_debug_break << 8u) | (0u << 0u);
132 
133     public inline nothrow ulong MakeSystemCallPtrAddress(int systemCall)
134     {
135         return trapTableBaseAddress + cast<ulong>(systemCall) * 8u;
136     }
137 
138     public class SystemCall
139     {
140         public nothrow SystemCall(Machine* machine_Kernel* kernel_ProcessTable* processTable_Process* process_
141             SystemCallHandler handler_byte x_byte y_byte z_ulong ax_ulong bx_ulong cx_ulong dx_ulong ex_) : 
142             machine(machine_)kernel(kernel_)processTable(processTable_)process(process_)
143             handler(handler_)x(x_)y(y_)z(z_)ax(ax_)bx(bx_)cx(cx_)dx(dx_)ex(ex_)result(0)
144         {
145         }
146         public nothrow string ToString() const
147         {
148             string s;
149             s.Append(SystemCallName(y)).Append(".ax=").Append(ToHexString(ax)).Append(".bx=").Append(ToHexString(bx)).Append(".cx=").Append(ToHexString(cx)).Append(".dx=");
150             s.Append(ToHexString(dx)).Append(".ex=").Append(ToHexString(ex)).Append(".result=").Append(ToHexString(result));
151             return s;
152         }
153         public nothrow bool IsDebugBreak() const
154         {
155             return x == 0u && y == sys_debug_break && z == 0u;
156         }
157         public Machine* machine;
158         public Kernel* kernel;
159         public ProcessTable* processTable;
160         public Process* process;
161         public SystemCallHandler handler;
162         public byte x;
163         public byte y;
164         public byte z;
165         public ulong ax;
166         public ulong bx;
167         public ulong cx;
168         public ulong dx;
169         public ulong ex;
170         public long result;
171     }
172 
173     public delegate void SystemCallHandler(SystemCall& sc);
174 
175     public void SystemCallFiber(void* processParam)
176     {
177         Process* process = cast<Process*>(processParam);
178         while (true)
179         {
180             try
181             {
182                 process->systemCallReady = false;
183                 const SystemCall& sc = process->systemCall;
184                 if (Log())
185                 {
186                     LogMessage("sc.begin"sc.ToString());
187                 }
188                 SystemCallHandler handler = sc.handler;
189                 process->kernelStart = Now();
190                 handler(sc);
191             }
192             catch (const SystemError& systemError)
193             {
194                 process->lastError = systemError;
195                 process->systemCall.result = -1;
196                 string s = SystemCallName(process->systemCall.y);
197                 s.Append(" failed\n");
198                 Kernel& kernel = GetKernel();
199                 Debugger* debugger = kernel.GetDebugger();
200                 debugger->WriteOutput(cast<byte*>(cast<void*>(s.Chars()))s.Length());
201             }
202             catch (const Exception& ex)
203             {
204                 process->lastError = SystemError(EFAIL"system call failed: " + ex.ToString());
205                 process->systemCall.result = -1;
206             }
207             if (Log())
208             {
209                 string msg = process->systemCall.ToString();
210                 if (process->systemCall.result == -1)
211                 {
212                     msg.Append(".error=").Append(process->lastError.ToString());
213                 }
214                 LogMessage("sc.end"msg);
215             }
216             process->systemCallReady = true;
217             process->mode = Process.Mode.runningUser;
218             process->kernelTime = process->kernelTime + Now() - process->kernelStart;
219             OsSwitchToFiber(mainFiber);
220         }
221     }
222 
223     public void Exit(SystemCall& sc)
224     {
225         if (sc.x != 0u || sc.y != sys_exit || sc.z != 0u)
226         {
227             Panic("invalid exit parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
228         }
229         ushort exitCode = MakeProcessExitCode(0ucast<byte>(sc.ax));
230         Debugger* debugger = sc.kernel->GetDebugger();
231         Processor& processor = sc.machine->GetProcessor();
232         Process* process = sc.process;
233         ExitProcess(*sc.machine*sc.processTableprocessexitCode);
234         if (process->pid == sc.kernel->GetProgramPID())
235         {
236             processor.Exit();
237         }
238         debugger->Exit(process);
239     }
240 
241     public void Wait(SystemCall& sc)
242     {
243         if (sc.x != 0u || sc.y != sys_wait || sc.z != 0u)
244         {
245             Panic("invalid wait parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
246         }
247         int retval = WaitProcess(*sc.machine*sc.processTablesc.processsc.ax);
248         sc.result = retval;
249     }
250 
251     public void Fork(SystemCall& sc)
252     {
253         if (sc.x != 0u || sc.y != sys_fork || sc.z != 0u)
254         {
255             Panic("invalid fork parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
256         }
257         int retval = ForkProcess(*sc.machine*sc.processTablesc.process);
258         sc.result = retval;
259     }
260 
261     public void Exec(SystemCall& sc)
262     {
263         if (sc.x != 0u || sc.y != sys_exec || sc.z != 0u)
264         {
265             Panic("invalid exec parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
266         }
267         Exec(*sc.machine*sc.processTablesc.processcast<int>(sc.ax)cast<int>(sc.bx)sc.cxcast<long>(sc.dx));
268         sc.result = cast<int>(sc.ax);
269     }
270 
271     public void Kill(SystemCall& sc)
272     {
273         if (sc.x != 0u || sc.y != sys_kill || sc.z != 0u)
274         {
275             Panic("invalid kill parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
276         }
277         SendSignalProcess(*sc.machine*sc.processTablesc.processcast<int>(sc.ax)cast<int>(sc.bx));
278         sc.result = 0;
279     }
280 
281     public void Create(SystemCall& sc)
282     {
283         if (sc.x != 0u || sc.y != sys_create || sc.z != 0u)
284         {
285             Panic("invalid create parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
286         }
287         sc.result = Create(*sc.machinesc.processcast<ulong>(sc.ax)cast<int>(sc.bx));
288     }
289 
290     public void Open(SystemCall& sc)
291     {
292         if (sc.x != 0u || sc.y != sys_open || sc.z != 0u)
293         {
294             Panic("invalid open parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
295         }
296         sc.result = Open(*sc.machinesc.processcast<ulong>(sc.ax)cast<OpenFlags>(cast<int>(sc.bx))cast<int>(sc.cx));
297     }
298 
299     public void Close(SystemCall& sc)
300     {
301         if (sc.x != 0u || sc.y != sys_close || sc.z != 0u)
302         {
303             Panic("invalid close parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
304         }
305         Close(*sc.machinesc.processcast<int>(sc.ax));
306         sc.result = 0;
307     }
308 
309     public void Read(SystemCall& sc)
310     {
311         if (sc.x != 0u || sc.y != sys_read || sc.z != 0u)
312         {
313             Panic("invalid read parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
314         }
315         long retval = Read(*sc.machinesc.processcast<int>(sc.ax)sc.bxcast<long>(sc.cx));
316         sc.result = retval;
317     }
318 
319     public void Write(SystemCall& sc)
320     {
321         if (sc.x != 0u || sc.y != sys_write || sc.z != 0u)
322         {
323             Panic("invalid write parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
324         }
325         long retval = Write(*sc.machinesc.processcast<int>(sc.ax)sc.bxcast<long>(sc.cx));
326         sc.result = retval;
327     }
328 
329     public void Seek(SystemCall& sc)
330     {
331         if (sc.x != 0u || sc.y != sys_seek || sc.z != 0u)
332         {
333             Panic("invalid seek parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
334         }
335         int fd = cast<int>(sc.ax);
336         long pos = cast<long>(sc.bx);
337         Origin origin = cast<Origin>(cast<byte>(sc.cx));
338         long retval = Seek(*sc.machinesc.processfdposorigin);
339         sc.result = retval;
340     }
341 
342     public void Tell(SystemCall& sc)
343     {
344         if (sc.x != 0u || sc.y != sys_seek || sc.z != 0u)
345         {
346             Panic("invalid tell parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
347         }
348         int fd = cast<int>(sc.ax);
349         long retval = Tell(*sc.machinesc.processfd);
350         sc.result = retval;
351     }
352 
353     public void PoolEnd(SystemCall& sc)
354     {
355         if (sc.x != 0u || sc.y != sys_pool_end || sc.z != 0u)
356         {
357             Panic("invalid pool_end parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
358         }
359         long retval = cast<long>(sc.process->poolEnd);
360         sc.result = retval;
361     }
362 
363     public void SetPoolEnd(SystemCall& sc)
364     {
365         if (sc.x != 0u || sc.y != sys_set_pool_end || sc.z != 0u)
366         {
367             Panic("invalid set_pool_end parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
368         }
369         sc.result = SetPoolEndProcess(*sc.machinesc.processsc.ax);
370     }
371 
372     public void DebugBreak(SystemCall& sc)
373     {
374         if (sc.x != 0u || sc.y != sys_debug_break || sc.z != 0u)
375         {
376             Panic("invalid debug break parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
377         }
378         Debugger* debugger = sc.kernel->GetDebugger();
379         debugger->Run(sc.process);
380     }
381 
382     public void StackTrace(SystemCall& sc)
383     {
384         if (sc.x != 0u || sc.y != sys_stack_trace || sc.z != 0u)
385         {
386             Panic("invalid stack trace parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
387         }
388         ulong fp = sc.machine->GetRegisters().Get(regFP);
389         ulong buffer = sc.ax;
390         long count = cast<long>(sc.bx);
391         GetProcessStackTrace(*sc.machinesc.processfpbuffercount);
392         sc.result = 0;
393     }
394 
395     public void Throw(SystemCall& sc)
396     {
397         if (sc.x != 0u || sc.y != sys_throw || sc.z != 0u)
398         {
399             Panic("invalid throw parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
400         }
401         ulong exceptionAddress = sc.ax;
402         ulong exceptionClassId = sc.bx;
403         ulong fp = sc.machine->GetRegisters().Get(regFP);
404         sc.process->currentExceptionAddress = exceptionAddress;
405         sc.process->currentExceptionClassId = exceptionClassId;
406         DispatchException(*sc.machinesc.processfp);
407         sc.result = 0;
408     }
409 
410     public void Catch(SystemCall& sc)
411     {
412         if (sc.x != 0u || sc.y != sys_catch || sc.z != 0u)
413         {
414             Panic("invalid catch parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
415         }
416         ulong exceptionAddress = sc.process->currentExceptionAddress;
417         sc.result = cast<long>(exceptionAddress);
418     }
419 
420     public void Resume(SystemCall& sc)
421     {
422         if (sc.x != 0u || sc.y != sys_resume || sc.z != 0u)
423         {
424             Panic("invalid resume parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
425         }
426         ulong fp = sc.machine->GetRegisters().Get(regFP);
427         ContinueExceptionDispatch(*sc.machinesc.processfp);
428         sc.result = 0;
429     }
430 
431     public void GetSystemError(SystemCall& sc)
432     {
433         if (sc.x != 0u || sc.y != sys_get_system_error || sc.z != 0u)
434         {
435             Panic("invalid get_system_error parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
436         }
437         ulong errorCodeAddress = sc.ax;
438         ulong bufferAddress = sc.bx;
439         long count = cast<long>(sc.cx);
440         GetProcessSystemError(*sc.machinesc.processerrorCodeAddressbufferAddresscount);
441         sc.result = 0;
442     }
443 
444     public void GetCurrentTimePoint(SystemCall& sc)
445     {
446         if (sc.x != 0u || sc.y != sys_get_current_time_point || sc.z != 0u)
447         {
448             Panic("invalid get_current_time_point parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
449         }
450         long currentTimePoint = System.Now().Rep();
451         sc.result = currentTimePoint;
452     }
453 
454     public void Sleep(SystemCall& sc)
455     {
456         if (sc.x != 0u || sc.y != sys_sleep || sc.z != 0u)
457         {
458             Panic("invalid sleep parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
459         }
460         Duration sleepDuration(cast<long>(sc.ax));
461         if (sleepDuration.Rep() < 0)
462         {
463             throw SystemError(EINVAL"invalid sleep duration");
464         }
465         TimePoint dueTime = System.Now() + sleepDuration;
466         SleepProcess(sc.processwakeupEventcast<ulong>(dueTime.Rep())0u);
467         SleepingProcessQueue.Instance().AddProcess(sc.process);
468         sc.result = 0;
469     }
470 
471     public void GetCurrentDate(SystemCall& sc)
472     {
473         if (sc.x != 0u || sc.y != sys_get_current_date || sc.z != 0u)
474         {
475             Panic("invalid get_current_date parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
476         }
477         ulong yearAddress = sc.ax;
478         ulong monthAddress = sc.bx;
479         ulong dayAddress = sc.cx;
480         if (yearAddress == 0u)
481         {
482             throw SystemError(EINVAL"year pointer is null");
483         }
484         else if (monthAddress == 0u)
485         {
486             throw SystemError(EINVAL"month pointer is null");
487         }
488         else if (dayAddress == 0u)
489         {
490             throw SystemError(EINVAL"day pointer is null");
491         }
492         Date date = System.GetCurrentDate();
493         short year = date.Year();
494         sbyte month = date.GetMonth();
495         sbyte day = date.Day();
496         WriteProcessMemory(*sc.machinesc.processyearAddresscast<ulong>(year)2uProtection.write);
497         WriteProcessMemory(*sc.machinesc.processmonthAddresscast<ulong>(month)1uProtection.write);
498         WriteProcessMemory(*sc.machinesc.processdayAddresscast<ulong>(day)1uProtection.write);
499     }
500 
501     public void GetCurrentDateTime(SystemCall& sc)
502     {
503         if (sc.x != 0u || sc.y != sys_get_current_date_time || sc.z != 0u)
504         {
505             Panic("invalid get_current_date_time parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
506         }
507         ulong yearAddress = sc.ax;
508         ulong monthAddress = sc.bx;
509         ulong dayAddress = sc.cx;
510         ulong secsAddress = sc.dx;
511         if (yearAddress == 0u)
512         {
513             throw SystemError(EINVAL"year pointer is null");
514         }
515         else if (monthAddress == 0u)
516         {
517             throw SystemError(EINVAL"month pointer is null");
518         }
519         else if (dayAddress == 0u)
520         {
521             throw SystemError(EINVAL"day pointer is null");
522         }
523         else if (secsAddress == 0u)
524         {
525             throw SystemError(EINVAL"secs pointer is null");
526         }
527         DateTime dateTime = GetCurrentDateTime();
528         Date date = dateTime.GetDate();
529         short year = date.Year();
530         sbyte month = date.GetMonth();
531         sbyte day = date.Day();
532         int secs = dateTime.Seconds();
533         WriteProcessMemory(*sc.machinesc.processyearAddresscast<ulong>(year)2uProtection.write);
534         WriteProcessMemory(*sc.machinesc.processmonthAddresscast<ulong>(month)1uProtection.write);
535         WriteProcessMemory(*sc.machinesc.processdayAddresscast<ulong>(day)1uProtection.write);
536         WriteProcessMemory(*sc.machinesc.processsecsAddresscast<ulong>(secs)4uProtection.write);
537     }
538 
539     public void Pow(SystemCall& sc)
540     {
541         if (sc.x != 0u || sc.y != sys_pow || sc.z != 0u)
542         {
543             Panic("invalid pow parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
544         }
545         double x = *cast<double*>(cast<void*>(&sc.ax));
546         double y = *cast<double*>(cast<void*>(&sc.bx));
547         double r = Pow(xy);
548         sc.result = *cast<long*>(cast<void*>(&r));
549     }
550 
551     public void GetRandomSeed(SystemCall& sc)
552     {
553         if (sc.x != 0u || sc.y != sys_get_random_seed || sc.z != 0u)
554         {
555             Panic("invalid get_random_seed parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
556         }
557         sc.result = RtGetRandomSeed();
558     }
559 
560     public void Link(SystemCall& sc)
561     {
562         if (sc.x != 0u || sc.y != sys_link || sc.z != 0u)
563         {
564             Panic("invalid link parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
565         }
566         Link(*sc.machinesc.processsc.axsc.bx);
567     }
568 
569     public void Unlink(SystemCall& sc)
570     {
571         if (sc.x != 0u || sc.y != sys_unlink || sc.z != 0u)
572         {
573             Panic("invalid unlink parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
574         }
575         Unlink(*sc.machinesc.processsc.ax);
576         sc.result = 0;
577     }
578 
579     public void Rename(SystemCall& sc)
580     {
581         if (sc.x != 0u || sc.y != sys_rename || sc.z != 0u)
582         {
583             Panic("invalid rename parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
584         }
585         Rename(*sc.machinesc.processsc.axsc.bx);
586         sc.result = 0;
587     }
588 
589     public void Mkdir(SystemCall& sc)
590     {
591         if (sc.x != 0u || sc.y != sys_mkdir || sc.z != 0u)
592         {
593             Panic("invalid mkdir parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
594         }
595         Mkdir(*sc.machinesc.processsc.axcast<int>(sc.bx));
596     }
597 
598     public void OpenDir(SystemCall& sc)
599     {
600         if (sc.x != 0u || sc.y != sys_opendir || sc.z != 0u)
601         {
602             Panic("invalid opendir parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
603         }
604         sc.result = OpenDir(*sc.machinesc.processsc.ax);
605     }
606 
607     public void ReadDir(SystemCall& sc)
608     {
609         if (sc.x != 0u || sc.y != sys_readdir || sc.z != 0u)
610         {
611             Panic("invalid readdir parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
612         }
613         sc.result = ReadDir(*sc.machinesc.processcast<int>(sc.ax)sc.bxsc.cx);
614     }
615 
616     public void CloseDir(SystemCall& sc)
617     {
618         if (sc.x != 0u || sc.y != sys_closedir || sc.z != 0u)
619         {
620             Panic("invalid closedir parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
621         }
622         CloseDir(*sc.machinesc.processcast<int>(sc.ax));
623         sc.result = 0;
624     }
625 
626     public void GetCWD(SystemCall& sc)
627     {
628         if (sc.x != 0u || sc.y != sys_getcwd || sc.z != 0u)
629         {
630             Panic("invalid getcwd parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
631         }
632         GetCWD(*sc.machinesc.processsc.axcast<long>(sc.bx));
633         sc.result = 0;
634     }
635 
636     public void ChDir(SystemCall& sc)
637     {
638         if (sc.x != 0u || sc.y != sys_chdir || sc.z != 0u)
639         {
640             Panic("invalid chdir parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
641         }
642         ChDir(*sc.machinesc.processsc.ax);
643         sc.result = 0;
644     }
645 
646     public void Stat(SystemCall& sc)
647     {
648         if (sc.x != 0u || sc.y != sys_stat || sc.z != 0u)
649         {
650             Panic("invalid stat parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
651         }
652         Stat(*sc.machinesc.processsc.axsc.bx);
653         sc.result = 0;
654     }
655 
656     public void UMask(SystemCall& sc)
657     {
658         if (sc.x != 0u || sc.y != sys_umask || sc.z != 0u)
659         {
660             Panic("invalid umask parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
661         }
662         sc.result = UMask(*sc.machinesc.processcast<int>(sc.ax));
663     }
664 
665     public void IOCtl(SystemCall& sc)
666     {
667         if (sc.x != 0u || sc.y != sys_ioctl || sc.z != 0u)
668         {
669             Panic("invalid ioctl parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
670         }
671         IOCtl(*sc.machinesc.processcast<int>(sc.ax)cast<int>(sc.bx)sc.cxcast<long>(sc.dx));
672         sc.result = 0;
673     }
674 
675     public void Chmod(SystemCall& sc)
676     {
677         if (sc.x != 0u || sc.y != sys_chmod || sc.z != 0u)
678         {
679             Panic("invalid chmod parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
680         }
681         Chmod(*sc.machinesc.processsc.axcast<int>(sc.bx));
682         sc.result = 0;
683     }
684 
685     public void Chown(SystemCall& sc)
686     {
687         if (sc.x != 0u || sc.y != sys_chown || sc.z != 0u)
688         {
689             Panic("invalid chmod parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
690         }
691         Chown(*sc.machinesc.processsc.axcast<int>(sc.bx)cast<int>(sc.cx));
692         sc.result = 0;
693     }
694 
695     public void UTime(SystemCall& sc)
696     {
697         if (sc.x != 0u || sc.y != sys_utime || sc.z != 0u)
698         {
699             Panic("invalid utime parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
700         }
701         UTime(*sc.machinesc.processsc.axsc.bx);
702     }
703 
704     public void GetUID(SystemCall& sc)
705     {
706         if (sc.x != 0u || sc.y != sys_getuid || sc.z != 0u)
707         {
708             Panic("invalid getuid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
709         }
710         sc.result = sc.process->uid;
711     }
712 
713     public void SetUID(SystemCall& sc)
714     {
715         if (sc.x != 0u || sc.y != sys_setuid || sc.z != 0u)
716         {
717             Panic("invalid setuid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
718         }
719         SetUIDProcess(sc.processcast<int>(sc.ax));
720         sc.result = 0;
721     }
722 
723     public void GetGID(SystemCall& sc)
724     {
725         if (sc.x != 0u || sc.y != sys_getgid || sc.z != 0u)
726         {
727             Panic("invalid getgid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
728         }
729         sc.result = sc.process->gid;
730     }
731 
732     public void SetGID(SystemCall& sc)
733     {
734         if (sc.x != 0u || sc.y != sys_setgid || sc.z != 0u)
735         {
736             Panic("invalid setgid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
737         }
738         SetGIDProcess(sc.processcast<int>(sc.ax));
739         sc.result = 0;
740     }
741 
742     public void GetPID(SystemCall& sc)
743     {
744         if (sc.x != 0u || sc.y != sys_getpid || sc.z != 0u)
745         {
746             Panic("invalid getpid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
747         }
748         sc.result = sc.process->pid;
749     }
750 
751     public void GetPGID(SystemCall& sc)
752     {
753         if (sc.x != 0u || sc.y != sys_getpgid || sc.z != 0u)
754         {
755             Panic("invalid getpgid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
756         }
757         sc.result = sc.process->pgid;
758     }
759 
760     public void SetPGID(SystemCall& sc)
761     {
762         if (sc.x != 0u || sc.y != sys_setpgid || sc.z != 0u)
763         {
764             Panic("invalid setpgid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
765         }
766         Process* process = sc.process;
767         process->pgid = cast<int>(sc.ax);
768         sc.result = 0;
769     }
770 
771     public void GetFGPID(SystemCall& sc)
772     {
773         if (sc.x != 0u || sc.y != sys_getfgpid || sc.z != 0u)
774         {
775             Panic("invalid getfgpid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
776         }
777         int fd = cast<int>(sc.ax);
778         sc.result = GetFGPID(sc.processfd);
779     }
780 
781     public void SetFGPID(SystemCall& sc)
782     {
783         if (sc.x != 0u || sc.y != sys_setfgpid || sc.z != 0u)
784         {
785             Panic("invalid setfgpid parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
786         }
787         int fd = cast<int>(sc.ax);
788         int pid = cast<int>(sc.bx);
789         SetFGPID(sc.processfdpid);
790         sc.result = 0;
791     }
792 
793     public void Sync(SystemCall& sc)
794     {
795         if (sc.x != 0u || sc.y != sys_sync || sc.z != 0u)
796         {
797             Panic("invalid sync parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
798         }
799         GetMountTable().Flush();
800         sc.result = 0;
801     }
802 
803     public void Times(SystemCall& sc)
804     {
805         if (sc.x != 0u || sc.y != sys_times || sc.z != 0u)
806         {
807             Panic("invalid times parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
808         }
809         Times(*sc.machinesc.processsc.axsc.bxsc.cxsc.dx);
810         sc.result = 0;
811     }
812 
813     public void GetHostName(SystemCall& sc)
814     {
815         if (sc.x != 0u || sc.y != sys_get_host_name || sc.z != 0u)
816         {
817             Panic("invalid get_host_name parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
818         }
819         ulong bufferAddress = sc.ax;
820         int size = cast<int>(sc.bx);
821         const string& host = sc.kernel->Host();
822         if (size <= host.Length())
823         {
824             throw SystemError(ERANGE"get_host_name: buffer too small");
825         }
826         WriteProcessMemory(*sc.machinesc.processbufferAddresscast<byte*>(cast<void*>(host.Chars()))cast<ulong>(host.Length() + 1)Protection.write);
827         sc.result = 0;
828     }
829 
830     public void Dup(SystemCall& sc)
831     {
832         if (sc.x != 0u || sc.y != sys_dup || sc.z != 0u)
833         {
834             Panic("invalid dup parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
835         }
836         sc.result = Dup(sc.processcast<int>(sc.ax));
837     }
838 
839     public void Pipe(SystemCall& sc)
840     {
841         if (sc.x != 0u || sc.y != sys_pipe || sc.z != 0u)
842         {
843             Panic("invalid pipe parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
844         }
845         Pipe(*sc.machinesc.processsc.axsc.bx);
846         sc.result = 0;
847     }
848 
849     public void Log(SystemCall& sc)
850     {
851         if (sc.x != 0u || sc.y != sys_log || sc.z != 0u)
852         {
853             Panic("invalid log parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
854         }
855         if (cmsx.kernel.Log())
856         {
857             sc.result = 1;
858         }
859         else
860         {
861             sc.result = 0;
862         }
863     }
864 
865     public void LogMessage(SystemCall& sc)
866     {
867         if (sc.x != 0u || sc.y != sys_log_message || sc.z != 0u)
868         {
869             Panic("invalid log_message parameters: " + ToString(sc.x) + ", " + ToString(sc.y) + ", " + ToString(sc.z));
870         }
871         ulong methodAddress = sc.ax;
872         if (methodAddress == 0u)
873         {
874             throw SystemError(EINVAL"method address is null");
875         }
876         ulong msgAddress = sc.bx;
877         if (msgAddress == 0u)
878         {
879             throw SystemError(EINVAL"msg address is null");
880         }
881         string method;
882         ReadStringFromProcessMemory(*sc.machinesc.processmethodAddressmethod);
883         string msg;
884         ReadStringFromProcessMemory(*sc.machinesc.processmsgAddressmsg);
885         LogMessage(methodmsg);
886     }
887 }