📄 syscalls.c
字号:
/*****************************************************************************
SYSCALLS
EXPORTS:
void sys_exit(task_t *curr_task, int exit_code);
bool syscall(task_t *curr_task, volatile regs_t *regs);
*****************************************************************************/
#include <string.h> /* NULL */
#include <krnl.h>
#include <_sys.h> /* SYS_... */
/* IMPORTS
from MAIN.C */
extern task_t _tasks[];
int sleep_on(task_t *curr_task, wait_queue_t *queue, unsigned *timeout);
void kprintf(const char *fmt, ...);
/* from VIDEO.C */
void putch(console_t *con, unsigned char c);
/* from TIME.C */
unsigned long sys_time(void);
/*****************************************************************************
*****************************************************************************/
static unsigned long sys_sbrk(task_t *curr_task, long delta)
{
sect_t *sect;
sect = curr_task->sect + HEAP_SECT;
/* shrink heap */
if(delta < 0)
{
/* don't lower break value if delta is too large */
if((unsigned long)(-delta) < sect->size)
sect->size += delta;
}
/* grow heap */
else if(delta > 0)
{
/* don't increase break value if delta is too large */
if(delta + sect->size < MAX_HEAP_SIZE)
sect->size += delta;
}
/* return new or current break value */
return sect->adr + sect->size;
}
/*****************************************************************************
*****************************************************************************/
void sys_exit(task_t *curr_task, int exit_code)
{
curr_task->exit_code = exit_code;
curr_task->status = TS_ZOMBIE;
}
/*****************************************************************************
*****************************************************************************/
static bool sys_sleep(task_t *curr_task, unsigned timeout)
{
/* 'dummy' because wake_up() is not used; only the timeout */
static wait_queue_t dummy;
/**/
if(timeout != 0)
{
sleep_on(curr_task, &dummy, &timeout);
return false;
}
return true;
}
/*****************************************************************************
*****************************************************************************/
static int sys_write(task_t *curr_task, unsigned handle, void *bufp,
unsigned len)
{
char *buf = (char *)bufp;
unsigned pos;
for(pos = 0; pos < len; pos++)
{
putch(curr_task->vc, *buf);
buf++;
}
return len;
}
/*****************************************************************************
name: deq
action: tries to get byte from queue
returns:-1 if queue empty
0 if success (data set to value read from queue)
*****************************************************************************/
static int deq(queue_t *q, unsigned char *data)
{
/* if out_ptr reaches in_base, the queue is empty */
if(q->out_ptr == q->in_base)
return -1;
*data = q->data[q->out_ptr++];
if(q->out_ptr >= q->size)
q->out_ptr = 0;
return 0;
}
/*****************************************************************************
*****************************************************************************/
static int empty(queue_t *q)
{
return q->out_ptr == q->in_base;
}
/*****************************************************************************
*****************************************************************************/
static int sys_read(task_t *curr_task, unsigned handle, unsigned char *buf,
unsigned want)
{
console_t *con;
unsigned got;
queue_t *q;
con = curr_task->vc;
q = &con->keystrokes;
if(con->unbuffered)
want = 1;
for(got = 0; got < want; got++)
{
do
{
while(empty(q))
sleep_on(curr_task, &con->wait_queue, NULL);
} while(deq(q, buf) != 0);
if(*buf == '\0')
break;
buf++;
}
return got;
}
/*****************************************************************************
*****************************************************************************/
static int sys_ioctl(task_t *curr_task, unsigned handle,
unsigned char opcode, unsigned arg)
{
switch(opcode)
{
/* turn keyboard unbuffered on/off */
case 0:
switch(arg)
{
case 0:
case 1:
curr_task->vc->unbuffered = arg;
break;
default:
return -1;
}
break;
default:
return -1;
}
return 0;
}
/*****************************************************************************
returns nonzero if timeout while waiting for input
*****************************************************************************/
static int sys_select(task_t *curr_task, unsigned handle, unsigned timeout)
{
console_t *con;
queue_t *q;
con = curr_task->vc;
q = &con->keystrokes;
if(!empty(q))
return 0;
sleep_on(curr_task, &con->wait_queue, &timeout);
return timeout == 0;
}
/*****************************************************************************
*****************************************************************************/
bool syscall(task_t *curr_task, volatile regs_t *regs)
{
bool must_call_schedule = false;
switch(regs->eax)
{
case SYS_WRITE:
regs->eax = sys_write(curr_task, regs->edx,
(unsigned char *)regs->ebx,
regs->ecx);
break;
case SYS_READ:
regs->eax = sys_read(curr_task, regs->edx,
(unsigned char *)regs->ebx,
regs->ecx);
break;
case SYS_IOCTL:
regs->eax = sys_ioctl(curr_task, regs->edx,
regs->ebx, regs->ecx);
break;
case SYS_SELECT:
regs->eax = sys_select(curr_task, regs->edx,
regs->ebx);
break;
case SYS_SBRK:
regs->eax = sys_sbrk(curr_task, regs->ebx);
break;
case SYS_TIME:
regs->eax = sys_time();
break;
case SYS_EXIT:
sys_exit(curr_task, regs->ebx);
must_call_schedule = true;
break;
case SYS_SLEEP:
must_call_schedule = sys_sleep(curr_task, regs->ebx);
break;
default:
kprintf("Illegal syscall 0x%X; task %u killed\n",
regs->eax, curr_task - _tasks);
sys_exit(curr_task, -1);
must_call_schedule = true;
break;
}
return must_call_schedule;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -