Reorganized system call library; uses separate file per call now.
New configuration header file to include/ exclude functionality. Extracted privileged features from struct proc and create new struct priv. Renamed various system calls for readability.
This commit is contained in:
parent
355d22ff06
commit
42ab148155
|
@ -15,27 +15,23 @@ LDFLAGS = -i
|
||||||
|
|
||||||
HEAD = mpx.o
|
HEAD = mpx.o
|
||||||
OBJS = start.o protect.o klibc.o klib.o table.o main.o proc.o \
|
OBJS = start.o protect.o klibc.o klib.o table.o main.o proc.o \
|
||||||
i8259.o exception.o system.o clock.o misc.o
|
i8259.o exception.o system.o clock.o utility.o debug.o
|
||||||
SYS_OBJS = $s/proctl.o $s/copying.o $s/devio.o $s/sysctl.o $s/misc.o \
|
SYSTEM = system.a
|
||||||
$s/sigctl.o $s/tracing.o $s/clock.o $s/irqctl.o $s/debugging.o \
|
LIBS = -ltimers
|
||||||
$s/priority.o
|
|
||||||
LIBS = -ltimers
|
|
||||||
|
|
||||||
|
|
||||||
# What to make.
|
# What to make.
|
||||||
kernel build: $(HEAD) $(OBJS) $(SYS_OBJS)
|
all: build
|
||||||
$(LD) $(CFLAGS) $(LDFLAGS) -o kernel $(HEAD) $(OBJS) $(SYS_OBJS) $(LIBS)
|
kernel build install: $(HEAD) $(OBJS)
|
||||||
install -S 0 kernel
|
|
||||||
|
|
||||||
$(SYS_OBJS):
|
|
||||||
cd system && $(MAKE)
|
|
||||||
|
|
||||||
all install:
|
|
||||||
cd system && $(MAKE) -$(MAKEFLAGS) $@
|
cd system && $(MAKE) -$(MAKEFLAGS) $@
|
||||||
|
$(LD) $(CFLAGS) $(LDFLAGS) -o kernel \
|
||||||
|
$(HEAD) $(OBJS) \
|
||||||
|
$(SYSTEM) $(LIBS)
|
||||||
|
install -S 0 kernel
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
cd system && $(MAKE) -$(MAKEFLAGS) $@
|
cd system && $(MAKE) -$(MAKEFLAGS) $@
|
||||||
rm -f *.o *.bak kernel
|
rm -f *.a *.o *.bak kernel
|
||||||
|
|
||||||
depend:
|
depend:
|
||||||
cd system && $(MAKE) -$(MAKEFLAGS) $@
|
cd system && $(MAKE) -$(MAKEFLAGS) $@
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
* Important events that are handled by the CLOCK include alarm timers and
|
* Important events that are handled by the CLOCK include alarm timers and
|
||||||
* (re)scheduling user processes.
|
* (re)scheduling user processes.
|
||||||
* The CLOCK offers a direct interface to kernel processes. System services
|
* The CLOCK offers a direct interface to kernel processes. System services
|
||||||
* can access its services through system calls, such as sys_syncalrm(). The
|
* can access its services through system calls, such as sys_setalarm(). The
|
||||||
* CLOCK task thus is hidden for the outside.
|
* CLOCK task thus is hidden for the outside world.
|
||||||
*
|
*
|
||||||
* Changes:
|
* Changes:
|
||||||
* Mar 18, 2004 clock interface moved to SYSTEM task (Jorrit N. Herder)
|
* Mar 18, 2004 clock interface moved to SYSTEM task (Jorrit N. Herder)
|
||||||
|
@ -29,11 +29,10 @@
|
||||||
* The watchdog functions of expired timers are executed in do_clocktick().
|
* The watchdog functions of expired timers are executed in do_clocktick().
|
||||||
* It is crucial that watchdog functions cannot block, or the CLOCK task may
|
* It is crucial that watchdog functions cannot block, or the CLOCK task may
|
||||||
* be blocked. Do not send() a message when the receiver is not expecting it.
|
* be blocked. Do not send() a message when the receiver is not expecting it.
|
||||||
* The use of notify(), which always returns, is strictly preferred!
|
* Instead, notify(), which always returns, should be used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "debug.h"
|
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
|
@ -159,46 +158,31 @@ message *m_ptr; /* pointer to request message */
|
||||||
PRIVATE int clock_handler(hook)
|
PRIVATE int clock_handler(hook)
|
||||||
irq_hook_t *hook;
|
irq_hook_t *hook;
|
||||||
{
|
{
|
||||||
/* This executes on every clock tick (i.e., every time the timer chip
|
/* This executes on each clock tick (i.e., every time the timer chip generates
|
||||||
* generates an interrupt). It does a little bit of work so the clock
|
* an interrupt). It does a little bit of work so the clock task does not have
|
||||||
* task does not have to be called on every tick.
|
* to be called on every tick. The clock task is called when:
|
||||||
*
|
*
|
||||||
* Switch context to do_clocktick() if an alarm has gone off.
|
* (1) the scheduling quantum of the running process has expired, or
|
||||||
* Also switch there to reschedule if the reschedule will do something.
|
* (2) a timer has expired and the watchdog function should be run.
|
||||||
* This happens when
|
|
||||||
* (1) quantum has expired
|
|
||||||
* (2) current process received full quantum (as clock sampled it!)
|
|
||||||
* (3) something else is ready to run.
|
|
||||||
*
|
*
|
||||||
* Many global global and static variables are accessed here. The safety
|
* Many global global and static variables are accessed here. The safety of
|
||||||
* of this must be justified. Most of them are not changed here:
|
* this must be justified. All scheduling and message passing code acquires a
|
||||||
|
* lock by temporarily disabling interrupts, so no conflicts with calls from
|
||||||
|
* the task level can occur. Furthermore, interrupts are not reentrant, the
|
||||||
|
* interrupt handler cannot be bothered by other interrupts.
|
||||||
|
*
|
||||||
|
* Variables that are updated in the clock's interrupt handler:
|
||||||
|
* lost_ticks:
|
||||||
|
* Clock ticks counted outside the clock task. This for example
|
||||||
|
* is used when the boot monitor processes a real mode interrupt.
|
||||||
|
* realtime:
|
||||||
|
* The current uptime is incremented with all outstanding ticks.
|
||||||
* proc_ptr, bill_ptr:
|
* proc_ptr, bill_ptr:
|
||||||
* These are used for accounting. It does not matter if proc.c
|
* These are used for accounting. It does not matter if proc.c
|
||||||
* is changing them, provided they are always valid pointers,
|
* is changing them, provided they are always valid pointers,
|
||||||
* since at worst the previous process would be billed.
|
* since at worst the previous process would be billed.
|
||||||
* next_timeout, realtime, sched_ticks, bill_ptr, prev_ptr,
|
|
||||||
* These are tested to decide whether to call notify(). It
|
|
||||||
* does not matter if the test is sometimes (rarely) backwards
|
|
||||||
* due to a race, since this will only delay the high-level
|
|
||||||
* processing by one tick, or call the high level unnecessarily.
|
|
||||||
* The variables which are changed require more care:
|
|
||||||
* rp->p_user_time, rp->p_sys_time:
|
|
||||||
* These are protected by explicit locks in system.c.
|
|
||||||
* lost_ticks:
|
|
||||||
* Clock ticks counted outside the clock task.
|
|
||||||
* sched_ticks, prev_ptr:
|
|
||||||
* Updating these competes with similar code in do_clocktick().
|
|
||||||
* No lock is necessary, because if bad things happen here
|
|
||||||
* (like sched_ticks going negative), the code in do_clocktick()
|
|
||||||
* will restore the variables to reasonable values, and an
|
|
||||||
* occasional missed or extra sched() is harmless.
|
|
||||||
*
|
|
||||||
* Are these complications worth the trouble? Well, they make the system 15%
|
|
||||||
* faster on a 5MHz 8088, and make task debugging much easier since there are
|
|
||||||
* no task switches on an inactive system.
|
|
||||||
*/
|
*/
|
||||||
register unsigned ticks;
|
register unsigned ticks;
|
||||||
message m;
|
|
||||||
|
|
||||||
/* Acknowledge the PS/2 clock interrupt. */
|
/* Acknowledge the PS/2 clock interrupt. */
|
||||||
if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);
|
if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);
|
||||||
|
@ -215,17 +199,16 @@ irq_hook_t *hook;
|
||||||
*/
|
*/
|
||||||
proc_ptr->p_user_time += ticks;
|
proc_ptr->p_user_time += ticks;
|
||||||
if (proc_ptr != bill_ptr) bill_ptr->p_sys_time += ticks;
|
if (proc_ptr != bill_ptr) bill_ptr->p_sys_time += ticks;
|
||||||
if (proc_ptr->p_flags & PREEMPTIBLE) proc_ptr->p_sched_ticks -= ticks;
|
if (priv(proc_ptr)->s_flags & PREEMPTIBLE) proc_ptr->p_sched_ticks -= ticks;
|
||||||
|
|
||||||
/* Check if do_clocktick() must be called. Done for alarms and scheduling.
|
/* Check if do_clocktick() must be called. Done for alarms and scheduling.
|
||||||
* Some processes, such as the kernel tasks, cannot be preempted.
|
* Some processes, such as the kernel tasks, cannot be preempted.
|
||||||
*/
|
*/
|
||||||
if ((next_timeout <= realtime) || (proc_ptr->p_sched_ticks <= 0)) {
|
if ((next_timeout <= realtime) || (proc_ptr->p_sched_ticks <= 0)) {
|
||||||
prev_ptr = proc_ptr; /* store running process */
|
prev_ptr = proc_ptr; /* store running process */
|
||||||
m.NOTIFY_TYPE = HARD_INT;
|
lock_alert(HARDWARE, CLOCK); /* send notification */
|
||||||
lock_notify(CLOCK, &m); /* send event notification */
|
|
||||||
}
|
}
|
||||||
return(1); /* reenable clock interrupts */
|
return(1); /* reenable interrupts */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -289,6 +272,7 @@ PRIVATE void init_clock()
|
||||||
enable_irq(&clock_hook); /* ready for clock interrupts */
|
enable_irq(&clock_hook); /* ready for clock interrupts */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* clock_stop *
|
* clock_stop *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
/* General constants used by the kernel. */
|
/* General macros and constants used by the kernel. */
|
||||||
|
#ifndef CONST_H
|
||||||
|
#define CONST_H
|
||||||
|
|
||||||
#include <ibm/interrupt.h> /* interrupt numbers and hardware vectors */
|
#include <ibm/interrupt.h> /* interrupt numbers and hardware vectors */
|
||||||
#include <ibm/ports.h> /* port addresses and magic numbers */
|
#include <ibm/ports.h> /* port addresses and magic numbers */
|
||||||
#include <ibm/bios.h> /* BIOS addresses, sizes and magic numbers */
|
#include <ibm/bios.h> /* BIOS addresses, sizes and magic numbers */
|
||||||
#include <ibm/cpu.h> /* BIOS addresses, sizes and magic numbers */
|
#include <ibm/cpu.h> /* BIOS addresses, sizes and magic numbers */
|
||||||
#include <minix/config.h>
|
#include <minix/config.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
/* To translate an address in kernel space to a physical address. This is
|
/* To translate an address in kernel space to a physical address. This is
|
||||||
* the same as umap_local(proc_ptr, D, vir, sizeof(*vir)), but less costly.
|
* the same as umap_local(proc_ptr, D, vir, sizeof(*vir)), but less costly.
|
||||||
*/
|
*/
|
||||||
#define vir2phys(vir) (kinfo.data_base + (vir_bytes) (vir))
|
#define vir2phys(vir) (kinfo.data_base + (vir_bytes) (vir))
|
||||||
|
|
||||||
/* Constants used in virtual_copy(). Values must be 0 and 1, respectively! */
|
|
||||||
#define _SRC_ 0
|
|
||||||
#define _DST_ 1
|
|
||||||
|
|
||||||
/* Translate a pointer to a field in a structure to a pointer to the structure
|
/* Translate a pointer to a field in a structure to a pointer to the structure
|
||||||
* itself. So it translates '&struct_ptr->field' back to 'struct_ptr'.
|
* itself. So it translates '&struct_ptr->field' back to 'struct_ptr'.
|
||||||
*/
|
*/
|
||||||
#define structof(type, field, ptr) \
|
#define structof(type, field, ptr) \
|
||||||
((type *) (((char *) (ptr)) - offsetof(type, field)))
|
((type *) (((char *) (ptr)) - offsetof(type, field)))
|
||||||
|
@ -24,30 +23,9 @@
|
||||||
/* How many bytes for the kernel stack. Space allocated in mpx.s. */
|
/* How many bytes for the kernel stack. Space allocated in mpx.s. */
|
||||||
#define K_STACK_BYTES 1024
|
#define K_STACK_BYTES 1024
|
||||||
|
|
||||||
/* How long should the process names be in the kernel? */
|
/* Constants used in virtual_copy(). Values must be 0 and 1, respectively. */
|
||||||
#define P_NAME_LEN 8
|
#define _SRC_ 0
|
||||||
|
#define _DST_ 1
|
||||||
/* Scheduling quantum. Number of ticks before preemption. */
|
|
||||||
#define SCHED_MILLISEC 100 /* rate to call scheduler */
|
|
||||||
#define SCHED_TICKS (SCHED_MILLISEC*HZ/1000) /* ticks per schedule */
|
|
||||||
|
|
||||||
/* How many bytes should the circular buffer for kernel diagnostics. */
|
|
||||||
#define KMESS_BUF_SIZE 256
|
|
||||||
|
|
||||||
/* Maximum size in bytes for (port,value)-pairs vector to copy in. */
|
|
||||||
#define VDEVIO_BUF_SIZE 64
|
|
||||||
|
|
||||||
/* How many elements in vector of virtual copy requests. */
|
|
||||||
#define VCOPY_VEC_SIZE 16
|
|
||||||
|
|
||||||
/* How many IRQ hooks are there in total. */
|
|
||||||
#define NR_IRQ_HOOKS 16
|
|
||||||
|
|
||||||
/* How many buffers for notification messages should there be? */
|
|
||||||
#define NR_NOTIFY_BUFS 32
|
|
||||||
|
|
||||||
/* Buffer to gather randomness. How many entries before wrapping? */
|
|
||||||
#define RANDOM_ELEMENTS 32
|
|
||||||
|
|
||||||
/* Constants and macros for bit map manipulation. */
|
/* Constants and macros for bit map manipulation. */
|
||||||
#define BITCHUNK_BITS (sizeof(bitchunk_t) * CHAR_BIT)
|
#define BITCHUNK_BITS (sizeof(bitchunk_t) * CHAR_BIT)
|
||||||
|
@ -58,6 +36,14 @@
|
||||||
#define SET_BIT(map,bit) ( MAP_CHUNK(map,bit) |= (1 << CHUNK_OFFSET(bit) )
|
#define SET_BIT(map,bit) ( MAP_CHUNK(map,bit) |= (1 << CHUNK_OFFSET(bit) )
|
||||||
#define UNSET_BIT(map,bit) ( MAP_CHUNK(map,bit) &= ~(1 << CHUNK_OFFSET(bit) )
|
#define UNSET_BIT(map,bit) ( MAP_CHUNK(map,bit) &= ~(1 << CHUNK_OFFSET(bit) )
|
||||||
|
|
||||||
|
#define get_sys_bit(map,bit) \
|
||||||
|
( MAP_CHUNK(map.chunk,bit) & (1 << CHUNK_OFFSET(bit) )
|
||||||
|
#define set_sys_bit(map,bit) \
|
||||||
|
( MAP_CHUNK(map.chunk,bit) |= (1 << CHUNK_OFFSET(bit) )
|
||||||
|
#define unset_sys_bit(map,bit) \
|
||||||
|
( MAP_CHUNK(map.chunk,bit) &= ~(1 << CHUNK_OFFSET(bit) )
|
||||||
|
#define NR_SYS_CHUNKS BITMAP_CHUNKS(NR_SYS_PROCS)
|
||||||
|
|
||||||
|
|
||||||
#if (CHIP == INTEL)
|
#if (CHIP == INTEL)
|
||||||
|
|
||||||
|
@ -70,29 +56,18 @@
|
||||||
#define IF_MASK 0x00000200
|
#define IF_MASK 0x00000200
|
||||||
#define IOPL_MASK 0x003000
|
#define IOPL_MASK 0x003000
|
||||||
|
|
||||||
#if ENABLE_LOCK_TIMING
|
/* Disable/ enable hardware interrupts. The parameters of lock() and unlock()
|
||||||
#define locktimestart(c, v) timer_start(c, v)
|
* are used when debugging is enabled. See debug.h for more information.
|
||||||
#define locktimeend(c) timer_end(c)
|
*/
|
||||||
#else
|
#define lock(c, v) intr_disable();
|
||||||
#define locktimestart(c, v)
|
#define unlock(c) intr_enable();
|
||||||
#define locktimeend(c)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLE_K_LOCKCHECK
|
|
||||||
#define lockcheck if(!(read_cpu_flags() & X86_FLAG_I)) kinfo.relocking++;
|
|
||||||
#else
|
|
||||||
#define lockcheck
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Disable/Enable hardware interrupts. */
|
|
||||||
#define lock(c, v) do { lockcheck; intr_disable(); locktimestart(c, v); } while(0)
|
|
||||||
#define unlock(c) do { locktimeend(c); intr_enable(); } while(0)
|
|
||||||
|
|
||||||
/* Sizes of memory tables. The boot monitor distinguishes three memory areas,
|
/* Sizes of memory tables. The boot monitor distinguishes three memory areas,
|
||||||
* namely low mem below 1M, 1M-16M, and mem after 16M. More chunks are needed
|
* namely low mem below 1M, 1M-16M, and mem after 16M. More chunks are needed
|
||||||
* for DOS MINIX.
|
* for DOS MINIX.
|
||||||
*/
|
*/
|
||||||
#define NR_MEMS 8 /* number of chunks of memory */
|
#define NR_MEMS 8
|
||||||
|
|
||||||
|
|
||||||
#endif /* (CHIP == INTEL) */
|
#endif /* (CHIP == INTEL) */
|
||||||
|
|
||||||
|
@ -100,7 +75,4 @@
|
||||||
/* M68000 specific constants go here. */
|
/* M68000 specific constants go here. */
|
||||||
#endif /* (CHIP == M68000) */
|
#endif /* (CHIP == M68000) */
|
||||||
|
|
||||||
#if ENABLE_INT_TIMING
|
#endif /* CONST_H */
|
||||||
#define INT_TIMING_BITS 12
|
|
||||||
#define INT_TIMING_ELEMENTS (1L << 12)
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
/* The system call implemented in this file:
|
/* This file implements kernel debugging functionality that is not included
|
||||||
* m_type: SYS_DEBUG
|
* in the standard kernel. Available functionality includes timing of lock
|
||||||
*
|
* functions and sanity checking of the scheduling queues.
|
||||||
* The parameters for this system call are:
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../kernel.h"
|
#include "kernel.h"
|
||||||
#include "../system.h"
|
#include "proc.h"
|
||||||
#include "../proc.h"
|
#include "debug.h"
|
||||||
#include "../glo.h"
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#if ENABLE_LOCK_TIMING
|
#if DEBUG_TIME_LOCKS /* only include code if enabled */
|
||||||
|
|
||||||
|
/* Data structures to store lock() timing data. */
|
||||||
|
struct lock_timingdata timingdata[TIMING_CATEGORIES];
|
||||||
static unsigned long starttimes[TIMING_CATEGORIES][2];
|
static unsigned long starttimes[TIMING_CATEGORIES][2];
|
||||||
|
|
||||||
#define HIGHCOUNT 0
|
#define HIGHCOUNT 0
|
||||||
|
@ -42,8 +42,6 @@ void timer_start(int cat, char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
read_tsc(&starttimes[cat][HIGHCOUNT], &starttimes[cat][LOWCOUNT]);
|
read_tsc(&starttimes[cat][HIGHCOUNT], &starttimes[cat][LOWCOUNT]);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void timer_end(int cat)
|
void timer_end(int cat)
|
||||||
|
@ -102,9 +100,10 @@ void timer_end(int cat)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif /* DEBUG_TIME_LOCKS */
|
||||||
|
|
||||||
#if ENABLE_K_DEBUGGING /* only include code if enabled */
|
|
||||||
|
#if DEBUG_SCHED_CHECK /* only include code if enabled */
|
||||||
|
|
||||||
#define PROCLIMIT 10000
|
#define PROCLIMIT 10000
|
||||||
|
|
||||||
|
@ -157,7 +156,7 @@ check_runqueues(char *when)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
|
for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
|
||||||
if(! isempty(xp) && xp->p_ready && ! xp->p_found) {
|
if(! isemptyp(xp) && xp->p_ready && ! xp->p_found) {
|
||||||
kprintf("scheduling error: ready not on queue: %s\n", (karg_t) when);
|
kprintf("scheduling error: ready not on queue: %s\n", (karg_t) when);
|
||||||
panic("ready proc not on scheduling queue", NO_NUM);
|
panic("ready proc not on scheduling queue", NO_NUM);
|
||||||
if(l++ > PROCLIMIT) { panic("loop in proc.t?", NO_NUM); }
|
if(l++ > PROCLIMIT) { panic("loop in proc.t?", NO_NUM); }
|
||||||
|
@ -165,8 +164,4 @@ check_runqueues(char *when)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*==========================================================================*
|
#endif /* DEBUG_SCHED_CHECK */
|
||||||
* do_debug *
|
|
||||||
*==========================================================================*/
|
|
||||||
|
|
||||||
#endif /* ENABLE_K_DEBUGGING */
|
|
|
@ -1,15 +1,74 @@
|
||||||
#ifndef DEBUG_H
|
#ifndef DEBUG_H
|
||||||
#define DEBUG_H
|
#define DEBUG_H
|
||||||
|
|
||||||
#include <minix/config.h>
|
/* This header file defines all debugging constants and macros, and declares
|
||||||
|
* some variables. Certain debugging features redefine standard constants
|
||||||
|
* and macros. Therefore, this header file should be included after the
|
||||||
|
* other kernel headers.
|
||||||
|
*/
|
||||||
|
|
||||||
#if ENABLE_LOCK_TIMING
|
#include "config.h"
|
||||||
|
|
||||||
|
/* It's interesting to measure the time spent withing locked regions, because
|
||||||
|
* this is the time that the system is deaf to interrupts.
|
||||||
|
*/
|
||||||
|
#if DEBUG_TIME_LOCKS
|
||||||
|
|
||||||
|
#define TIMING_POINTS 20 /* timing resolution */
|
||||||
|
#define TIMING_CATEGORIES 20
|
||||||
|
#define TIMING_NAME 10
|
||||||
|
|
||||||
|
/* Definition of the data structure to store lock() timing data. */
|
||||||
|
struct lock_timingdata {
|
||||||
|
char names[TIMING_NAME];
|
||||||
|
unsigned long lock_timings[TIMING_POINTS];
|
||||||
|
unsigned long lock_timings_range[2];
|
||||||
|
unsigned long binsize, resets, misses, measurements;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The data is declared here, but allocated in debug.c. */
|
||||||
|
extern struct lock_timingdata timingdata[TIMING_CATEGORIES];
|
||||||
|
|
||||||
|
/* Prototypes for the timing functionality. */
|
||||||
_PROTOTYPE( void timer_start, (int cat, char *name) );
|
_PROTOTYPE( void timer_start, (int cat, char *name) );
|
||||||
_PROTOTYPE( void timer_end, (int cat) );
|
_PROTOTYPE( void timer_end, (int cat) );
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLE_K_DEBUGGING /* debugging */
|
#define locktimestart(c, v) timer_start(c, v)
|
||||||
|
#define locktimeend(c) timer_end(c)
|
||||||
|
#else
|
||||||
|
#define locktimestart(c, v)
|
||||||
|
#define locktimeend(c)
|
||||||
|
#endif /* DEBUG_TIME_LOCKS */
|
||||||
|
|
||||||
|
|
||||||
|
/* The locking checks counts relocking situation, which are dangerous because
|
||||||
|
* the inner lock may unlock the outer one.
|
||||||
|
*/
|
||||||
|
#if DEBUG_LOCK_CHECK
|
||||||
|
#define lockcheck if (!(read_cpu_flags() & X86_FLAG_I)) kinfo.relocking++;
|
||||||
|
#else
|
||||||
|
#define lockcheck
|
||||||
|
#endif /* DEBUG_LOCK_CHECK */
|
||||||
|
|
||||||
|
|
||||||
|
/* This check makes sure that the scheduling queues are in a consistent state.
|
||||||
|
* The check is run when the queues are updated with ready() and unready().
|
||||||
|
*/
|
||||||
|
#if DEBUG_SCHED_CHECK
|
||||||
_PROTOTYPE( void check_runqueues, (char *when) );
|
_PROTOTYPE( void check_runqueues, (char *when) );
|
||||||
|
#endif /* DEBUG_SCHED_CHECK */
|
||||||
|
|
||||||
|
|
||||||
|
/* The timing and checking of kernel locking requires a redefine of the lock()
|
||||||
|
* and unlock() macros. That's done here. This redefine requires that this
|
||||||
|
* header is included after the other kernel headers.
|
||||||
|
*/
|
||||||
|
#if (DEBUG_TIME_LOCKS || DEBUG_LOCK_CHECK)
|
||||||
|
# undef lock
|
||||||
|
# define lock(c, v) do { lockcheck; intr_disable(); locktimestart(c, v); } while(0)
|
||||||
|
# undef unlock
|
||||||
|
# define unlock(c) do { locktimeend(c); intr_enable(); } while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* DEBUG_H */
|
|
||||||
|
#endif /* DEBUG_H */
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
/* This file contains a simple exception handler. Exceptions in user
|
/* This file contains a simple exception handler. Exceptions in user
|
||||||
* processes are converted to signals. Exceptions in the kernel, MM and
|
* processes are converted to signals. Exceptions in a kernel task cause
|
||||||
* FS cause a panic.
|
* a panic.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
* exception *
|
* exception *
|
||||||
|
|
12
kernel/glo.h
12
kernel/glo.h
|
@ -1,7 +1,10 @@
|
||||||
|
#ifndef GLO_H
|
||||||
|
#define GLO_H
|
||||||
|
|
||||||
/* Global variables used in the kernel. This file contains the declarations;
|
/* Global variables used in the kernel. This file contains the declarations;
|
||||||
* storage space for the variables is allocated in table.c, because EXTERN is
|
* storage space for the variables is allocated in table.c, because EXTERN is
|
||||||
* defined as extern unless the _TABLE definition is seen. We rely on the
|
* defined as extern unless the _TABLE definition is seen. We rely on the
|
||||||
* compiler's default initialization (0) for several global variables.
|
* compiler's default initialization (0) for several global variables.
|
||||||
*/
|
*/
|
||||||
#ifdef _TABLE
|
#ifdef _TABLE
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
|
@ -9,6 +12,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <minix/config.h>
|
#include <minix/config.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
/* Variables relating to shutting down MINIX. */
|
/* Variables relating to shutting down MINIX. */
|
||||||
EXTERN char kernel_exception; /* TRUE after system exceptions */
|
EXTERN char kernel_exception; /* TRUE after system exceptions */
|
||||||
|
@ -42,11 +46,6 @@ EXTERN irq_hook_t *irq_handlers[NR_IRQ_VECTORS];/* list of IRQ handlers */
|
||||||
EXTERN int irq_actids[NR_IRQ_VECTORS]; /* IRQ ID bits active */
|
EXTERN int irq_actids[NR_IRQ_VECTORS]; /* IRQ ID bits active */
|
||||||
EXTERN int irq_use; /* map of all in-use irq's */
|
EXTERN int irq_use; /* map of all in-use irq's */
|
||||||
|
|
||||||
/* Data structure to store lock() timing data. */
|
|
||||||
#if ENABLE_LOCK_TIMING
|
|
||||||
EXTERN struct lock_timedata timingdata[TIMING_CATEGORIES];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Miscellaneous. */
|
/* Miscellaneous. */
|
||||||
EXTERN reg_t mon_ss, mon_sp; /* boot monitor stack */
|
EXTERN reg_t mon_ss, mon_sp; /* boot monitor stack */
|
||||||
EXTERN int mon_return; /* true if we can return to monitor */
|
EXTERN int mon_return; /* true if we can return to monitor */
|
||||||
|
@ -63,3 +62,4 @@ EXTERN _PROTOTYPE( void (*level0_func), (void) );
|
||||||
/* M68000 specific variables go here. */
|
/* M68000 specific variables go here. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* GLO_H */
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "debug.h"
|
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
|
|
||||||
#define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
|
#define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
|
||||||
|
@ -49,7 +48,8 @@ int mine;
|
||||||
*/
|
*/
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
lock(6, "intr_init");
|
intr_disable();
|
||||||
|
|
||||||
if (machine.protected) {
|
if (machine.protected) {
|
||||||
/* The AT and newer PS/2 have two interrupt controllers, one master,
|
/* The AT and newer PS/2 have two interrupt controllers, one master,
|
||||||
* one slaved at IRQ 2. (We don't have to deal with the PC that
|
* one slaved at IRQ 2. (We don't have to deal with the PC that
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef IPC_H
|
||||||
|
#define IPC_H
|
||||||
|
|
||||||
/* Masks and flags for system calls. */
|
/* Masks and flags for system calls. */
|
||||||
#define SYSCALL_FUNC 0x0F /* mask for system call function */
|
#define SYSCALL_FUNC 0x0F /* mask for system call function */
|
||||||
#define SYSCALL_FLAGS 0xF0 /* mask for system call flags */
|
#define SYSCALL_FLAGS 0xF0 /* mask for system call flags */
|
||||||
|
@ -11,10 +14,13 @@
|
||||||
#define RECEIVE 2 /* function code for receiving messages */
|
#define RECEIVE 2 /* function code for receiving messages */
|
||||||
#define SENDREC 3 /* function code for SEND + RECEIVE */
|
#define SENDREC 3 /* function code for SEND + RECEIVE */
|
||||||
#define NOTIFY 4 /* function code for notifications */
|
#define NOTIFY 4 /* function code for notifications */
|
||||||
|
#define ALERT 5 /* function code for alerting */
|
||||||
|
|
||||||
/* Call masks indicating which system calls a process can make. */
|
/* Call masks indicating which system calls a process can make. */
|
||||||
#define EMPTY_CALL_MASK (0)
|
#define EMPTY_CALL_MASK (0)
|
||||||
#define USER_CALL_MASK (1 << SENDREC)
|
#define _USER_CALL_MASK ((1 << SENDREC) | (1 << ALERT))
|
||||||
#define SYSTEM_CALL_MASK (~0)
|
#define SYSTEM_CALL_MASK (~0)
|
||||||
|
#define USER_CALL_MASK (~0)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* IPC_H */
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef KERNEL_H
|
||||||
|
#define KERNEL_H
|
||||||
|
|
||||||
/* This is the master header for the kernel. It includes some other files
|
/* This is the master header for the kernel. It includes some other files
|
||||||
* and defines the principal constants.
|
* and defines the principal constants.
|
||||||
*/
|
*/
|
||||||
|
@ -19,8 +22,13 @@
|
||||||
#include <ibm/portio.h> /* device I/O and toggle interrupts */
|
#include <ibm/portio.h> /* device I/O and toggle interrupts */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "const.h" /* kernel constants */
|
/* Important kernel header files. */
|
||||||
#include "type.h" /* kernel type definitions */
|
#include "config.h" /* configuration, MUST be first */
|
||||||
#include "proto.h" /* kernel function prototypes */
|
#include "const.h" /* constants, MUST be second */
|
||||||
#include "glo.h" /* kernel global variables */
|
#include "type.h" /* type definitions, MUST be third */
|
||||||
|
#include "proto.h" /* function prototypes */
|
||||||
|
#include "glo.h" /* global variables */
|
||||||
|
#include "ipc.h" /* IPC constants */
|
||||||
|
#include "debug.h" /* debugging, MUST be last kernel header */
|
||||||
|
|
||||||
|
#endif /* KERNEL_H */
|
||||||
|
|
|
@ -9,14 +9,13 @@
|
||||||
* kmemset: set n bytes to c starting at pointer p
|
* kmemset: set n bytes to c starting at pointer p
|
||||||
* kprintf: printf for the kernel (see working below)
|
* kprintf: printf for the kernel (see working below)
|
||||||
* kstrcmp: lexicographical comparison of two strings
|
* kstrcmp: lexicographical comparison of two strings
|
||||||
* kstrlen: get number of non-null characters in string
|
|
||||||
* kstrncpy: copy string and pad or copy up to n chars
|
* kstrncpy: copy string and pad or copy up to n chars
|
||||||
*
|
*
|
||||||
* This file contains the routines that take care of kernel messages, i.e.,
|
* This file contains the routines that take care of kernel messages, i.e.,
|
||||||
* diagnostic output within the kernel. Kernel messages are not directly
|
* diagnostic output within the kernel. Kernel messages are not directly
|
||||||
* displayed on the console, because this must be done by the PRINT driver.
|
* displayed on the console, because this must be done by the PRINT driver.
|
||||||
* Instead, the kernel accumulates characters in a buffer and notifies the
|
* Instead, the kernel accumulates characters in a buffer and notifies the
|
||||||
* PRINT driver when a new message is ready.
|
* output driver when a new message is ready.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
@ -154,63 +153,31 @@ int c; /* character to append */
|
||||||
/* Accumulate a single character for a kernel message. Send a notification
|
/* Accumulate a single character for a kernel message. Send a notification
|
||||||
* the to PRINTF_PROC driver if an END_OF_KMESS is encountered.
|
* the to PRINTF_PROC driver if an END_OF_KMESS is encountered.
|
||||||
*/
|
*/
|
||||||
message m;
|
|
||||||
if (c != END_OF_KMESS) {
|
if (c != END_OF_KMESS) {
|
||||||
kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
|
kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
|
||||||
if (kmess.km_size < KMESS_BUF_SIZE)
|
if (kmess.km_size < KMESS_BUF_SIZE)
|
||||||
kmess.km_size += 1;
|
kmess.km_size += 1;
|
||||||
kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
|
kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
|
||||||
} else {
|
} else {
|
||||||
m.NOTIFY_TYPE = NEW_KMESS;
|
lock_alert(SYSTEM, PRINTF_PROC);
|
||||||
lock_notify(PRINTF_PROC, &m);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*=========================================================================*
|
|
||||||
* kstrlen *
|
|
||||||
*=========================================================================*/
|
|
||||||
PUBLIC size_t kstrlen(const char *org)
|
|
||||||
{
|
|
||||||
register const char *s = org;
|
|
||||||
while (*s++)
|
|
||||||
/* EMPTY */ ;
|
|
||||||
return --s - org;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*=========================================================================*
|
/*=========================================================================*
|
||||||
* kstrcmp *
|
* kstrcmp *
|
||||||
*=========================================================================*/
|
*=========================================================================*/
|
||||||
int kstrcmp(register const char *s1, register const char *s2)
|
int kstrcmp(register const char *s1, register const char *s2)
|
||||||
{
|
{
|
||||||
while (*s1 == *s2++) {
|
while (*s1 == *s2++)
|
||||||
if (*s1++ == '\0') return 0;
|
if (*s1++ == '\0') return 0;
|
||||||
}
|
|
||||||
if (*s1 == '\0') return -1;
|
if (*s1 == '\0') return -1;
|
||||||
if (*--s2 == '\0') return 1;
|
if (*--s2 == '\0') return 1;
|
||||||
return (unsigned char) *s1 - (unsigned char) *s2;
|
return (unsigned char) *s1 - (unsigned char) *s2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*=========================================================================*
|
|
||||||
* kstrncmp *
|
|
||||||
*=========================================================================*/
|
|
||||||
PUBLIC int kstrncmp(register const char *s1, register const char *s2, register size_t n)
|
|
||||||
{
|
|
||||||
while (n > 0 && *s1 == *s2++) {
|
|
||||||
if (*s1++ == '\0') return 0;
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
if (n > 0) {
|
|
||||||
if (*s1 == '\0') return -1;
|
|
||||||
if (*--s2 == '\0') return 1;
|
|
||||||
return (unsigned char) *s1 - (unsigned char) *s2;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*=========================================================================*
|
/*=========================================================================*
|
||||||
* kstrncpy *
|
* kstrncpy *
|
||||||
*=========================================================================*/
|
*=========================================================================*/
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include <minix/callnr.h>
|
#include <minix/callnr.h>
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "sendmask.h"
|
|
||||||
|
|
||||||
/* Prototype declarations for PRIVATE functions. */
|
/* Prototype declarations for PRIVATE functions. */
|
||||||
FORWARD _PROTOTYPE( void announce, (void));
|
FORWARD _PROTOTYPE( void announce, (void));
|
||||||
|
@ -33,7 +32,8 @@ PUBLIC void main()
|
||||||
{
|
{
|
||||||
/* Start the ball rolling. */
|
/* Start the ball rolling. */
|
||||||
register struct proc *rp;
|
register struct proc *rp;
|
||||||
register int i;
|
register struct priv *sp;
|
||||||
|
register int i,s;
|
||||||
int hdrindex; /* index to array of a.out headers */
|
int hdrindex; /* index to array of a.out headers */
|
||||||
phys_clicks text_base;
|
phys_clicks text_base;
|
||||||
vir_clicks text_clicks;
|
vir_clicks text_clicks;
|
||||||
|
@ -46,13 +46,19 @@ PUBLIC void main()
|
||||||
intr_init(1);
|
intr_init(1);
|
||||||
|
|
||||||
/* Clear the process table. Anounce each slot as empty and set up mappings
|
/* Clear the process table. Anounce each slot as empty and set up mappings
|
||||||
* for proc_addr() and proc_nr() macros.
|
* for proc_addr() and proc_nr() macros. Do the same for the table with
|
||||||
|
* system properties structures.
|
||||||
*/
|
*/
|
||||||
for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) {
|
for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) {
|
||||||
rp->p_rts_flags = SLOT_FREE; /* initialize free slot */
|
rp->p_rts_flags = SLOT_FREE; /* initialize free slot */
|
||||||
rp->p_nr = i; /* proc number from ptr */
|
rp->p_nr = i; /* proc number from ptr */
|
||||||
(pproc_addr + NR_TASKS)[i] = rp; /* proc ptr from number */
|
(pproc_addr + NR_TASKS)[i] = rp; /* proc ptr from number */
|
||||||
}
|
}
|
||||||
|
for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
|
||||||
|
sp->s_proc_nr = NONE; /* initialize as free */
|
||||||
|
sp->s_id = i; /* priv structure index */
|
||||||
|
ppriv_addr[i] = sp; /* priv ptr from number */
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up proc table entries for tasks and servers. The stacks of the
|
/* Set up proc table entries for tasks and servers. The stacks of the
|
||||||
* kernel tasks are initialized to an array in data space. The stacks
|
* kernel tasks are initialized to an array in data space. The stacks
|
||||||
|
@ -65,23 +71,23 @@ PUBLIC void main()
|
||||||
/* Task stacks. */
|
/* Task stacks. */
|
||||||
ktsb = (reg_t) t_stack;
|
ktsb = (reg_t) t_stack;
|
||||||
|
|
||||||
for (i=0; i < IMAGE_SIZE; ++i) {
|
for (i=0; i < NR_BOOT_PROCS; ++i) {
|
||||||
ip = &image[i]; /* t's task attributes */
|
ip = &image[i]; /* process' attributes */
|
||||||
rp = proc_addr(ip->proc_nr); /* t's process slot */
|
(void) init_proc(ip->proc_nr, NONE); /* initialize new process */
|
||||||
|
rp = proc_addr(ip->proc_nr); /* get process pointer */
|
||||||
kstrncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set name */
|
kstrncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set name */
|
||||||
rp->p_name[P_NAME_LEN-1] = '\0'; /* just for safety */
|
rp->p_name[P_NAME_LEN-1] = '\0'; /* just for safety */
|
||||||
rp->p_flags = ip->flags; /* process flags */
|
|
||||||
rp->p_max_priority = ip->priority; /* max scheduling priority */
|
rp->p_max_priority = ip->priority; /* max scheduling priority */
|
||||||
rp->p_priority = ip->priority; /* current priority */
|
rp->p_priority = ip->priority; /* current priority */
|
||||||
rp->p_quantum_size = ip->quantum; /* quantum size in ticks */
|
rp->p_quantum_size = ip->quantum; /* quantum size in ticks */
|
||||||
rp->p_sched_ticks = ip->quantum; /* current credit */
|
rp->p_sched_ticks = ip->quantum; /* current credit */
|
||||||
rp->p_full_quantums = QUANTUMS(ip->priority); /* quantums left */
|
rp->p_full_quantums = QUANTUMS(ip->priority); /* quantums left */
|
||||||
rp->p_call_mask = ip->call_mask; /* allowed system calls */
|
rp->p_priv->s_flags = ip->flags; /* process flags */
|
||||||
rp->p_sendmask = ip->sendmask; /* sendmask protection */
|
rp->p_priv->s_call_mask = ip->call_mask;/* allowed system calls */
|
||||||
if (i-NR_TASKS < 0) { /* part of the kernel? */
|
if (i-NR_TASKS < 0) { /* part of the kernel? */
|
||||||
if (ip->stksize > 0) { /* HARDWARE stack size is 0 */
|
if (ip->stksize > 0) { /* HARDWARE stack size is 0 */
|
||||||
rp->p_stguard = (reg_t *) ktsb;
|
rp->p_priv->s_stack_guard = (reg_t *) ktsb;
|
||||||
*rp->p_stguard = STACK_GUARD;
|
*rp->p_priv->s_stack_guard = STACK_GUARD;
|
||||||
}
|
}
|
||||||
ktsb += ip->stksize; /* point to high end of stack */
|
ktsb += ip->stksize; /* point to high end of stack */
|
||||||
rp->p_reg.sp = ktsb; /* this task's initial stack ptr */
|
rp->p_reg.sp = ktsb; /* this task's initial stack ptr */
|
||||||
|
@ -126,9 +132,6 @@ PUBLIC void main()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set ready. The HARDWARE task is never ready. */
|
/* Set ready. The HARDWARE task is never ready. */
|
||||||
#if ENABLE_K_DEBUGGING
|
|
||||||
rp->p_ready = 0;
|
|
||||||
#endif
|
|
||||||
if (rp->p_nr != HARDWARE) lock_ready(rp);
|
if (rp->p_nr != HARDWARE) lock_ready(rp);
|
||||||
rp->p_rts_flags = 0;
|
rp->p_rts_flags = 0;
|
||||||
|
|
||||||
|
@ -198,12 +201,6 @@ int how; /* reason to shut down */
|
||||||
return; /* await sys_abort() from TTY */
|
return; /* await sys_abort() from TTY */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The TTY expects two HARD_STOP notifications. One to switch to the
|
|
||||||
* primary console for stop sequence output, and one to actually exit.
|
|
||||||
*/
|
|
||||||
m.NOTIFY_TYPE = HARD_STOP;
|
|
||||||
lock_notify(TTY, &m);
|
|
||||||
|
|
||||||
/* Allow processes to be scheduled to clean up, unless a CPU exception
|
/* Allow processes to be scheduled to clean up, unless a CPU exception
|
||||||
* occurred. This is done by setting a timer. The timer argument passes
|
* occurred. This is done by setting a timer. The timer argument passes
|
||||||
* the shutdown status.
|
* the shutdown status.
|
||||||
|
|
225
kernel/proc.c
225
kernel/proc.c
|
@ -38,14 +38,10 @@
|
||||||
* nonempty lists. As shown above, this is not required with pointer pointers.
|
* nonempty lists. As shown above, this is not required with pointer pointers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "kernel.h"
|
|
||||||
#include <minix/callnr.h>
|
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
|
#include <minix/callnr.h>
|
||||||
|
#include "kernel.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "const.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "ipc.h"
|
|
||||||
#include "sendmask.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Scheduling and message passing functions. The functions are available to
|
/* Scheduling and message passing functions. The functions are available to
|
||||||
|
@ -56,6 +52,7 @@ FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst,
|
||||||
message *m_ptr, unsigned flags) );
|
message *m_ptr, unsigned flags) );
|
||||||
FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, int src,
|
FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, int src,
|
||||||
message *m_ptr, unsigned flags) );
|
message *m_ptr, unsigned flags) );
|
||||||
|
FORWARD _PROTOTYPE( int mini_alert, (struct proc *caller_ptr, int dst) );
|
||||||
FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst,
|
FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst,
|
||||||
message *m_ptr ) );
|
message *m_ptr ) );
|
||||||
|
|
||||||
|
@ -64,12 +61,22 @@ FORWARD _PROTOTYPE( void unready, (struct proc *rp) );
|
||||||
FORWARD _PROTOTYPE( void sched, (struct proc *rp) );
|
FORWARD _PROTOTYPE( void sched, (struct proc *rp) );
|
||||||
FORWARD _PROTOTYPE( void pick_proc, (void) );
|
FORWARD _PROTOTYPE( void pick_proc, (void) );
|
||||||
|
|
||||||
#define BuildMess(m,n) \
|
|
||||||
|
#define BuildOldMess(m,n) \
|
||||||
(m).NOTIFY_SOURCE = (n)->n_source, \
|
(m).NOTIFY_SOURCE = (n)->n_source, \
|
||||||
(m).NOTIFY_TYPE = (n)->n_type, \
|
(m).NOTIFY_TYPE = (n)->n_type, \
|
||||||
(m).NOTIFY_FLAGS = (n)->n_flags, \
|
(m).NOTIFY_FLAGS = (n)->n_flags, \
|
||||||
(m).NOTIFY_ARG = (n)->n_arg;
|
(m).NOTIFY_ARG = (n)->n_arg;
|
||||||
|
|
||||||
|
#define BuildMess(m_ptr, src, dst_ptr) \
|
||||||
|
(m_ptr)->m_source = (src); \
|
||||||
|
(m_ptr)->m_type = NOTIFY_FROM(src); \
|
||||||
|
(m_ptr)->NOTIFY_TIMESTAMP = get_uptime(); \
|
||||||
|
if ((src) == HARDWARE) { \
|
||||||
|
(m_ptr)->NOTIFY_ARG = priv(dst_ptr)->s_int_pending; \
|
||||||
|
priv(dst_ptr)->s_int_pending = 0; \
|
||||||
|
}
|
||||||
|
|
||||||
#if (CHIP == INTEL)
|
#if (CHIP == INTEL)
|
||||||
#define CopyMess(s,sp,sm,dp,dm) \
|
#define CopyMess(s,sp,sm,dp,dm) \
|
||||||
cp_mess(s, (sp)->p_memmap[D].mem_phys, (vir_bytes)sm, (dp)->p_memmap[D].mem_phys, (vir_bytes)dm)
|
cp_mess(s, (sp)->p_memmap[D].mem_phys, (vir_bytes)sm, (dp)->p_memmap[D].mem_phys, (vir_bytes)dm)
|
||||||
|
@ -107,7 +114,7 @@ message *m_ptr; /* pointer to message in the caller's space */
|
||||||
* kernel may only be SENDREC, because tasks always reply and may not block
|
* kernel may only be SENDREC, because tasks always reply and may not block
|
||||||
* if the caller doesn't do receive().
|
* if the caller doesn't do receive().
|
||||||
*/
|
*/
|
||||||
if (! (caller_ptr->p_call_mask & (1 << function)) ||
|
if (! (priv(caller_ptr)->s_call_mask & (1 << function)) ||
|
||||||
(iskerneln(src_dst) && function != SENDREC))
|
(iskerneln(src_dst) && function != SENDREC))
|
||||||
return(ECALLDENIED);
|
return(ECALLDENIED);
|
||||||
|
|
||||||
|
@ -115,6 +122,7 @@ message *m_ptr; /* pointer to message in the caller's space */
|
||||||
if (! (isokprocn(src_dst) || src_dst == ANY || function == ECHO))
|
if (! (isokprocn(src_dst) || src_dst == ANY || function == ECHO))
|
||||||
return(EBADSRCDST);
|
return(EBADSRCDST);
|
||||||
|
|
||||||
|
#if DEAD_CODE /* temporarily disabled for testing ALERT */
|
||||||
/* Check validity of message pointer. */
|
/* Check validity of message pointer. */
|
||||||
vb = (vir_bytes) m_ptr;
|
vb = (vir_bytes) m_ptr;
|
||||||
vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */
|
vlo = vb >> CLICK_SHIFT; /* vir click for bottom of message */
|
||||||
|
@ -132,6 +140,7 @@ message *m_ptr; /* pointer to message in the caller's space */
|
||||||
if (vhi < vlo ||
|
if (vhi < vlo ||
|
||||||
vhi - caller_ptr->p_memmap[D].mem_vir >= caller_ptr->p_memmap[D].mem_len)
|
vhi - caller_ptr->p_memmap[D].mem_vir >= caller_ptr->p_memmap[D].mem_len)
|
||||||
return(EFAULT);
|
return(EFAULT);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Now check if the call is known and try to perform the request. The only
|
/* Now check if the call is known and try to perform the request. The only
|
||||||
|
@ -169,6 +178,9 @@ message *m_ptr; /* pointer to message in the caller's space */
|
||||||
case RECEIVE:
|
case RECEIVE:
|
||||||
result = mini_receive(caller_ptr, src_dst, m_ptr, flags);
|
result = mini_receive(caller_ptr, src_dst, m_ptr, flags);
|
||||||
break;
|
break;
|
||||||
|
case ALERT:
|
||||||
|
result = mini_alert(caller_ptr, src_dst);
|
||||||
|
break;
|
||||||
case NOTIFY:
|
case NOTIFY:
|
||||||
result = mini_notify(caller_ptr, src_dst, m_ptr);
|
result = mini_notify(caller_ptr, src_dst, m_ptr);
|
||||||
break;
|
break;
|
||||||
|
@ -182,14 +194,16 @@ message *m_ptr; /* pointer to message in the caller's space */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the caller made a successfull, blocking system call it's priority may
|
/* If the caller made a successfull, blocking system call it's priority may
|
||||||
* be raised. The priority have been lowered if a process consumed to many
|
* be raised. The priority may have been lowered if a process consumed too
|
||||||
* full quantums in a row to prevent damage from infinite loops
|
* many full quantums in a row to prevent damage from infinite loops
|
||||||
*/
|
*/
|
||||||
|
#if DEAD_CODE /* temporarily disabled for testing ALERT */
|
||||||
if ((caller_ptr->p_priority > caller_ptr->p_max_priority) &&
|
if ((caller_ptr->p_priority > caller_ptr->p_max_priority) &&
|
||||||
! (flags & NON_BLOCKING) && (result == OK)) {
|
! (flags & NON_BLOCKING) && (result == OK)) {
|
||||||
caller_ptr->p_priority = caller_ptr->p_max_priority;
|
caller_ptr->p_priority = caller_ptr->p_max_priority;
|
||||||
caller_ptr->p_full_quantums = QUANTUMS(caller_ptr->p_priority);
|
caller_ptr->p_full_quantums = QUANTUMS(caller_ptr->p_priority);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Now, return the result of the system call to the caller. */
|
/* Now, return the result of the system call to the caller. */
|
||||||
return(result);
|
return(result);
|
||||||
|
@ -264,6 +278,9 @@ unsigned flags; /* system call flags */
|
||||||
register struct notification **ntf_q_pp;
|
register struct notification **ntf_q_pp;
|
||||||
message m;
|
message m;
|
||||||
int bit_nr;
|
int bit_nr;
|
||||||
|
sys_map_t *map;
|
||||||
|
bitchunk_t *chunk;
|
||||||
|
int i, src_id, src_proc_nr;
|
||||||
|
|
||||||
/* Check to see if a message from desired source is already available.
|
/* Check to see if a message from desired source is already available.
|
||||||
* The caller's SENDING flag may be set if SENDREC couldn't send. If it is
|
* The caller's SENDING flag may be set if SENDREC couldn't send. If it is
|
||||||
|
@ -271,6 +288,48 @@ unsigned flags; /* system call flags */
|
||||||
*/
|
*/
|
||||||
if (!(caller_ptr->p_rts_flags & SENDING)) {
|
if (!(caller_ptr->p_rts_flags & SENDING)) {
|
||||||
|
|
||||||
|
/* Check if there are pending notifications, except for SENDREC. */
|
||||||
|
if (! (flags & FRESH_ANSWER)) {
|
||||||
|
|
||||||
|
map = &priv(caller_ptr)->s_notify_pending;
|
||||||
|
for (chunk=&map->chunk[0]; chunk<&map->chunk[NR_SYS_CHUNKS]; chunk++) {
|
||||||
|
|
||||||
|
/* Find a pending notification from the requested source. */
|
||||||
|
if (! *chunk) continue; /* no bits in chunk */
|
||||||
|
for (i=0; ! (*chunk & (1<<i)); ++i) {} /* look up the bit */
|
||||||
|
src_id = (chunk - &map->chunk[0]) * BITCHUNK_BITS + i;
|
||||||
|
if (src_id >= NR_SYS_PROCS) break; /* out of range */
|
||||||
|
src_proc_nr = id_to_nr(src_id); /* get source proc */
|
||||||
|
if (src!=ANY && src!=src_proc_nr) continue; /* source not ok */
|
||||||
|
*chunk &= ~(1 << i); /* no longer pending */
|
||||||
|
|
||||||
|
/* Found a suitable source, deliver the notification message. */
|
||||||
|
BuildMess(&m, src_proc_nr, caller_ptr); /* assemble message */
|
||||||
|
CopyMess(src_proc_nr, proc_addr(HARDWARE), &m, caller_ptr, m_ptr);
|
||||||
|
return(OK); /* report success */
|
||||||
|
}
|
||||||
|
|
||||||
|
ntf_q_pp = &caller_ptr->p_ntf_q; /* get pointer pointer */
|
||||||
|
while (*ntf_q_pp != NULL) {
|
||||||
|
if (src == ANY || src == (*ntf_q_pp)->n_source) {
|
||||||
|
/* Found notification. Assemble and copy message. */
|
||||||
|
BuildOldMess(m, *ntf_q_pp);
|
||||||
|
if (m.m_source == HARDWARE) {
|
||||||
|
m.NOTIFY_ARG = caller_ptr->p_priv->s_int_pending;
|
||||||
|
caller_ptr->p_priv->s_int_pending = 0;
|
||||||
|
}
|
||||||
|
CopyMess((*ntf_q_pp)->n_source, proc_addr(HARDWARE), &m,
|
||||||
|
caller_ptr, m_ptr);
|
||||||
|
/* Remove notification from queue and bit map. */
|
||||||
|
bit_nr = (int) (*ntf_q_pp - ¬ify_buffer[0]);
|
||||||
|
*ntf_q_pp = (*ntf_q_pp)->n_next;/* remove from queue */
|
||||||
|
free_bit(bit_nr, notify_bitmap, NR_NOTIFY_BUFS);
|
||||||
|
return(OK); /* report success */
|
||||||
|
}
|
||||||
|
ntf_q_pp = &(*ntf_q_pp)->n_next; /* proceed to next */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check caller queue. Use pointer pointers to keep code simple. */
|
/* Check caller queue. Use pointer pointers to keep code simple. */
|
||||||
xpp = &caller_ptr->p_caller_q;
|
xpp = &caller_ptr->p_caller_q;
|
||||||
while (*xpp != NIL_PROC) {
|
while (*xpp != NIL_PROC) {
|
||||||
|
@ -284,25 +343,6 @@ unsigned flags; /* system call flags */
|
||||||
xpp = &(*xpp)->p_q_link; /* proceed to next */
|
xpp = &(*xpp)->p_q_link; /* proceed to next */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if there are pending notifications, except for SENDREC. */
|
|
||||||
if (! (flags & FRESH_ANSWER)) {
|
|
||||||
|
|
||||||
ntf_q_pp = &caller_ptr->p_ntf_q; /* get pointer pointer */
|
|
||||||
while (*ntf_q_pp != NULL) {
|
|
||||||
if (src == ANY || src == (*ntf_q_pp)->n_source) {
|
|
||||||
/* Found notification. Assemble and copy message. */
|
|
||||||
BuildMess(m, *ntf_q_pp);
|
|
||||||
CopyMess((*ntf_q_pp)->n_source, proc_addr(HARDWARE), &m,
|
|
||||||
caller_ptr, m_ptr);
|
|
||||||
/* Remove notification from queue and bit map. */
|
|
||||||
bit_nr = (int) (*ntf_q_pp - ¬ify_buffer[0]);
|
|
||||||
*ntf_q_pp = (*ntf_q_pp)->n_next;/* remove from queue */
|
|
||||||
free_bit(bit_nr, notify_bitmap, NR_NOTIFY_BUFS);
|
|
||||||
return(OK); /* report success */
|
|
||||||
}
|
|
||||||
ntf_q_pp = &(*ntf_q_pp)->n_next; /* proceed to next */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No suitable message is available or the caller couldn't send in SENDREC.
|
/* No suitable message is available or the caller couldn't send in SENDREC.
|
||||||
|
@ -320,6 +360,45 @@ unsigned flags; /* system call flags */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* mini_alert *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE int mini_alert(caller_ptr, dst)
|
||||||
|
register struct proc *caller_ptr; /* sender of the notification */
|
||||||
|
int dst; /* which process to notify */
|
||||||
|
{
|
||||||
|
register struct proc *dst_ptr = proc_addr(dst);
|
||||||
|
int src_id; /* source id for late delivery */
|
||||||
|
message m; /* the notification message */
|
||||||
|
|
||||||
|
/* Check to see if target is blocked waiting for this message. A process
|
||||||
|
* can be both sending and receiving during a SENDREC system call.
|
||||||
|
*/
|
||||||
|
if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING &&
|
||||||
|
(dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) {
|
||||||
|
|
||||||
|
/* Destination is indeed waiting for a message. Assemble a notification
|
||||||
|
* message and deliver it. Copy from pseudo-source HARDWARE, since the
|
||||||
|
* message is in the kernel's address space.
|
||||||
|
*/
|
||||||
|
BuildMess(&m, proc_nr(caller_ptr), dst_ptr);
|
||||||
|
CopyMess(proc_nr(caller_ptr), proc_addr(HARDWARE), &m,
|
||||||
|
dst_ptr, dst_ptr->p_messbuf);
|
||||||
|
dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */
|
||||||
|
if (dst_ptr->p_rts_flags == 0) ready(dst_ptr);
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destination is not ready to receive the notification. Add it to the
|
||||||
|
* bit map with pending notifications. Note the indirectness: the system id
|
||||||
|
* instead of the process number is used in the pending bit map.
|
||||||
|
*/
|
||||||
|
src_id = priv(caller_ptr)->s_id;
|
||||||
|
set_sys_bit(priv(dst_ptr)->s_notify_pending, src_id);
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* mini_notify *
|
* mini_notify *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -337,15 +416,22 @@ message *m_ptr; /* pointer to message buffer */
|
||||||
/* Check to see if target is blocked waiting for this message. A process
|
/* Check to see if target is blocked waiting for this message. A process
|
||||||
* can be both sending and receiving during a SENDREC system call.
|
* can be both sending and receiving during a SENDREC system call.
|
||||||
*/
|
*/
|
||||||
if ( (dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING &&
|
if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING &&
|
||||||
(dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) {
|
(dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) {
|
||||||
|
|
||||||
/* Destination is indeed waiting for this message. */
|
/* Destination is indeed waiting for this message. Check if the source
|
||||||
CopyMess(proc_nr(caller_ptr), caller_ptr, m_ptr,
|
* is HARDWARE; this is a special case that gets the map of pending
|
||||||
dst_ptr, dst_ptr->p_messbuf);
|
* interrupts as an argument. Then deliver the notification message.
|
||||||
dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */
|
*/
|
||||||
if (dst_ptr->p_rts_flags == 0) ready(dst_ptr);
|
if (proc_nr(caller_ptr) == HARDWARE) {
|
||||||
return(OK);
|
m_ptr->NOTIFY_ARG = priv(dst_ptr)->s_int_pending;
|
||||||
|
priv(dst_ptr)->s_int_pending = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyMess(proc_nr(caller_ptr), caller_ptr, m_ptr, dst_ptr, dst_ptr->p_messbuf);
|
||||||
|
dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */
|
||||||
|
if (dst_ptr->p_rts_flags == 0) ready(dst_ptr);
|
||||||
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destination is not ready. Add the notification to the pending queue.
|
/* Destination is not ready. Add the notification to the pending queue.
|
||||||
|
@ -389,26 +475,27 @@ message *m_ptr; /* pointer to message buffer */
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
* lock_notify *
|
* lock_notify *
|
||||||
*==========================================================================*/
|
*==========================================================================*/
|
||||||
PUBLIC int lock_notify(dst, m_ptr)
|
PUBLIC int lock_alert(src, dst)
|
||||||
int dst; /* to whom is message being sent? */
|
int src; /* sender of the notification */
|
||||||
message *m_ptr; /* pointer to message buffer */
|
int dst; /* who is to be notified */
|
||||||
{
|
{
|
||||||
/* Safe gateway to mini_notify() for tasks and interrupt handlers. MINIX
|
/* Safe gateway to mini_notify() for tasks and interrupt handlers. The sender
|
||||||
|
* is explicitely given to prevent confusion where the call comes from. MINIX
|
||||||
* kernel is not reentrant, which means to interrupts are disabled after
|
* kernel is not reentrant, which means to interrupts are disabled after
|
||||||
* the first kernel entry (hardware interrupt, trap, or exception). Locking
|
* the first kernel entry (hardware interrupt, trap, or exception). Locking
|
||||||
* work is done by temporarily disabling interrupts.
|
* is done by temporarily disabling interrupts.
|
||||||
*/
|
*/
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
/* Exception or interrupt occurred, thus already locked. */
|
/* Exception or interrupt occurred, thus already locked. */
|
||||||
if (k_reenter >= 0) {
|
if (k_reenter >= 0) {
|
||||||
result = mini_notify(proc_addr(HARDWARE), dst, m_ptr);
|
result = mini_alert(proc_addr(src), dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call from task level, locking is required. */
|
/* Call from task level, locking is required. */
|
||||||
else {
|
else {
|
||||||
lock(0, "notify");
|
lock(0, "alert");
|
||||||
result = mini_notify(proc_ptr, dst, m_ptr);
|
result = mini_alert(proc_addr(src), dst);
|
||||||
unlock(0);
|
unlock(0);
|
||||||
}
|
}
|
||||||
return(result);
|
return(result);
|
||||||
|
@ -424,11 +511,9 @@ register struct proc *rp; /* this process is now runnable */
|
||||||
/* Add 'rp' to one of the queues of runnable processes. */
|
/* Add 'rp' to one of the queues of runnable processes. */
|
||||||
register int q = rp->p_priority; /* scheduling queue to use */
|
register int q = rp->p_priority; /* scheduling queue to use */
|
||||||
|
|
||||||
#if ENABLE_K_DEBUGGING
|
#if DEBUG_SCHED_CHECK
|
||||||
if(rp->p_ready) {
|
check_runqueues("ready");
|
||||||
kprintf("ready() already ready process\n", NO_NUM);
|
if(rp->p_ready) kprintf("ready() already ready process\n", NO_NUM);
|
||||||
}
|
|
||||||
rp->p_ready = 1;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Processes, in principle, are added to the end of the queue. However,
|
/* Processes, in principle, are added to the end of the queue. However,
|
||||||
|
@ -439,7 +524,7 @@ register struct proc *rp; /* this process is now runnable */
|
||||||
rdy_head[q] = rdy_tail[q] = rp; /* create a new queue */
|
rdy_head[q] = rdy_tail[q] = rp; /* create a new queue */
|
||||||
rp->p_nextready = NIL_PROC; /* mark new end */
|
rp->p_nextready = NIL_PROC; /* mark new end */
|
||||||
}
|
}
|
||||||
else if (rp->p_flags & SCHED_Q_HEAD) { /* add to head of queue */
|
else if (priv(rp)->s_flags & RDY_Q_HEAD) { /* add to head of queue */
|
||||||
rp->p_nextready = rdy_head[q]; /* chain head of queue */
|
rp->p_nextready = rdy_head[q]; /* chain head of queue */
|
||||||
rdy_head[q] = rp; /* set new queue head */
|
rdy_head[q] = rp; /* set new queue head */
|
||||||
}
|
}
|
||||||
|
@ -449,6 +534,11 @@ register struct proc *rp; /* this process is now runnable */
|
||||||
rp->p_nextready = NIL_PROC; /* mark new end */
|
rp->p_nextready = NIL_PROC; /* mark new end */
|
||||||
}
|
}
|
||||||
pick_proc(); /* select next to run */
|
pick_proc(); /* select next to run */
|
||||||
|
|
||||||
|
#if DEBUG_SCHED_CHECK
|
||||||
|
rp->p_ready = 1;
|
||||||
|
check_runqueues("ready");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -463,19 +553,17 @@ register struct proc *rp; /* this process is no longer runnable */
|
||||||
register struct proc **xpp; /* iterate over queue */
|
register struct proc **xpp; /* iterate over queue */
|
||||||
register struct proc *prev_xp;
|
register struct proc *prev_xp;
|
||||||
|
|
||||||
#if ENABLE_K_DEBUGGING
|
|
||||||
if(!rp->p_ready) {
|
|
||||||
kprintf("unready() already unready process\n", NO_NUM);
|
|
||||||
}
|
|
||||||
rp->p_ready = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Side-effect for kernel: check if the task's stack still is ok? */
|
/* Side-effect for kernel: check if the task's stack still is ok? */
|
||||||
if (iskernelp(rp)) {
|
if (iskernelp(rp)) {
|
||||||
if (*rp->p_stguard != STACK_GUARD)
|
if (*priv(rp)->s_stack_guard != STACK_GUARD)
|
||||||
panic("stack overrun by task", proc_nr(rp));
|
panic("stack overrun by task", proc_nr(rp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG_SCHED_CHECK
|
||||||
|
check_runqueues("unready");
|
||||||
|
if (! rp->p_ready) kprintf("unready() already unready process\n", NO_NUM);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Now make sure that the process is not in its ready queue. Remove the
|
/* Now make sure that the process is not in its ready queue. Remove the
|
||||||
* process if it is found. A process can be made unready even if it is not
|
* process if it is found. A process can be made unready even if it is not
|
||||||
* running by being sent a signal that kills it.
|
* running by being sent a signal that kills it.
|
||||||
|
@ -493,6 +581,11 @@ register struct proc *rp; /* this process is no longer runnable */
|
||||||
}
|
}
|
||||||
prev_xp = *xpp; /* save previous in chain */
|
prev_xp = *xpp; /* save previous in chain */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG_SCHED_CHECK
|
||||||
|
rp->p_ready = 0;
|
||||||
|
check_runqueues("unready");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -504,16 +597,19 @@ struct proc *sched_ptr; /* quantum eating process */
|
||||||
int q;
|
int q;
|
||||||
|
|
||||||
/* Check if this process is preemptible, otherwise leave it as is. */
|
/* Check if this process is preemptible, otherwise leave it as is. */
|
||||||
if (! (sched_ptr->p_flags & PREEMPTIBLE)) {
|
if (! (priv(sched_ptr)->s_flags & PREEMPTIBLE)) {
|
||||||
|
#if DEAD_CODE
|
||||||
kprintf("Warning, sched for nonpreemptible proc %d\n", sched_ptr->p_nr);
|
kprintf("Warning, sched for nonpreemptible proc %d\n", sched_ptr->p_nr);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEAD_CODE
|
||||||
if (sched_ptr->p_nr == IS_PROC_NR) {
|
if (sched_ptr->p_nr == IS_PROC_NR) {
|
||||||
kprintf("Scheduling IS: pri: %d, ", sched_ptr->p_priority);
|
kprintf("Scheduling IS: pri: %d, ", sched_ptr->p_priority);
|
||||||
kprintf("qua %d", sched_ptr->p_full_quantums);
|
kprintf("qua %d", sched_ptr->p_full_quantums);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* Process exceeded the maximum number of full quantums it is allowed
|
/* Process exceeded the maximum number of full quantums it is allowed
|
||||||
* to use in a row. Lower the process' priority, but make sure we don't
|
* to use in a row. Lower the process' priority, but make sure we don't
|
||||||
* end up in the IDLE queue. This helps to limit the damage caused by
|
* end up in the IDLE queue. This helps to limit the damage caused by
|
||||||
|
@ -525,8 +621,10 @@ struct proc *sched_ptr; /* quantum eating process */
|
||||||
unready(sched_ptr); /* remove from queues */
|
unready(sched_ptr); /* remove from queues */
|
||||||
sched_ptr->p_priority ++; /* lower priority */
|
sched_ptr->p_priority ++; /* lower priority */
|
||||||
ready(sched_ptr); /* add to new queue */
|
ready(sched_ptr); /* add to new queue */
|
||||||
|
#if DEAD_CODE
|
||||||
kprintf("Warning, proc %d got lower priority: ", sched_ptr->p_nr);
|
kprintf("Warning, proc %d got lower priority: ", sched_ptr->p_nr);
|
||||||
kprintf("%d\n", sched_ptr->p_priority);
|
kprintf("%d\n", sched_ptr->p_priority);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
sched_ptr->p_full_quantums = QUANTUMS(sched_ptr->p_priority);
|
sched_ptr->p_full_quantums = QUANTUMS(sched_ptr->p_priority);
|
||||||
}
|
}
|
||||||
|
@ -548,12 +646,13 @@ kprintf("%d\n", sched_ptr->p_priority);
|
||||||
sched_ptr->p_sched_ticks = sched_ptr->p_quantum_size;
|
sched_ptr->p_sched_ticks = sched_ptr->p_quantum_size;
|
||||||
pick_proc();
|
pick_proc();
|
||||||
|
|
||||||
|
#if DEAD_CODE
|
||||||
if (sched_ptr->p_nr == IS_PROC_NR) {
|
if (sched_ptr->p_nr == IS_PROC_NR) {
|
||||||
kprintf("Next proc: %d, ", next_ptr->p_nr);
|
kprintf("Next proc: %d, ", next_ptr->p_nr);
|
||||||
kprintf("pri: %d, ", next_ptr->p_priority);
|
kprintf("pri: %d, ", next_ptr->p_priority);
|
||||||
kprintf("qua: %d\n", next_ptr->p_full_quantums);
|
kprintf("qua: %d\n", next_ptr->p_full_quantums);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -576,7 +675,7 @@ PRIVATE void pick_proc()
|
||||||
for (q=0; q < NR_SCHED_QUEUES; q++) {
|
for (q=0; q < NR_SCHED_QUEUES; q++) {
|
||||||
if ( (rp = rdy_head[q]) != NIL_PROC) {
|
if ( (rp = rdy_head[q]) != NIL_PROC) {
|
||||||
next_ptr = rp; /* run process 'rp' next */
|
next_ptr = rp; /* run process 'rp' next */
|
||||||
if (rp->p_flags & BILLABLE)
|
if (priv(rp)->s_flags & BILLABLE)
|
||||||
bill_ptr = rp; /* bill for system time */
|
bill_ptr = rp; /* bill for system time */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
#include "protect.h"
|
#include "protect.h"
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
|
#include "priv.h"
|
||||||
|
|
||||||
struct proc {
|
struct proc {
|
||||||
struct stackframe_s p_reg; /* process' registers saved in stack frame */
|
struct stackframe_s p_reg; /* process' registers saved in stack frame */
|
||||||
|
@ -25,9 +26,8 @@ struct proc {
|
||||||
/* M68000 specific registers and FPU details go here. */
|
/* M68000 specific registers and FPU details go here. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
reg_t *p_stguard; /* stack guard word */
|
|
||||||
proc_nr_t p_nr; /* number of this process (for fast access) */
|
proc_nr_t p_nr; /* number of this process (for fast access) */
|
||||||
char p_flags; /* PREEMTIBLE, BILLABLE, etc. */
|
struct priv *p_priv; /* system privileges structure */
|
||||||
char p_rts_flags; /* SENDING, RECEIVING, etc. */
|
char p_rts_flags; /* SENDING, RECEIVING, etc. */
|
||||||
|
|
||||||
char p_priority; /* current scheduling priority */
|
char p_priority; /* current scheduling priority */
|
||||||
|
@ -36,11 +36,7 @@ struct proc {
|
||||||
char p_sched_ticks; /* number of scheduling ticks left */
|
char p_sched_ticks; /* number of scheduling ticks left */
|
||||||
char p_full_quantums; /* number of full quantums left */
|
char p_full_quantums; /* number of full quantums left */
|
||||||
|
|
||||||
char p_call_mask; /* bit map with allowed system call traps */
|
struct mem_map p_memmap[NR_LOCAL_SEGS]; /* memory map (T, D, S) */
|
||||||
send_mask_t p_sendmask; /* mask indicating to whom proc may send */
|
|
||||||
|
|
||||||
struct mem_map p_memmap[NR_LOCAL_SEGS]; /* local memory map (T, D, S) */
|
|
||||||
struct far_mem p_farmem[NR_REMOTE_SEGS]; /* remote memory map */
|
|
||||||
|
|
||||||
clock_t p_user_time; /* user time in ticks */
|
clock_t p_user_time; /* user time in ticks */
|
||||||
clock_t p_sys_time; /* sys time in ticks */
|
clock_t p_sys_time; /* sys time in ticks */
|
||||||
|
@ -53,19 +49,15 @@ struct proc {
|
||||||
proc_nr_t p_getfrom; /* from whom does process want to receive? */
|
proc_nr_t p_getfrom; /* from whom does process want to receive? */
|
||||||
proc_nr_t p_sendto; /* to whom does process want to send? */
|
proc_nr_t p_sendto; /* to whom does process want to send? */
|
||||||
|
|
||||||
timer_t p_alarm_timer; /* timer shared by different alarm types */
|
|
||||||
sigset_t p_pending; /* bit map for pending kernel signals */
|
sigset_t p_pending; /* bit map for pending kernel signals */
|
||||||
|
|
||||||
char p_name[P_NAME_LEN]; /* name of the process, including \0 */
|
char p_name[P_NAME_LEN]; /* name of the process, including \0 */
|
||||||
|
|
||||||
#if ENABLE_K_DEBUGGING
|
#if DEBUG_SCHED_CHECK
|
||||||
int p_ready, p_found;
|
int p_ready, p_found;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Guard word for task stacks. */
|
|
||||||
#define STACK_GUARD ((reg_t) (sizeof(reg_t) == 2 ? 0xBEEF : 0xDEADBEEF))
|
|
||||||
|
|
||||||
/* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */
|
/* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */
|
||||||
#define SLOT_FREE 0x01 /* process slot is free */
|
#define SLOT_FREE 0x01 /* process slot is free */
|
||||||
#define NO_MAP 0x02 /* keeps unmapped forked child from running */
|
#define NO_MAP 0x02 /* keeps unmapped forked child from running */
|
||||||
|
@ -74,11 +66,7 @@ struct proc {
|
||||||
#define SIGNALED 0x10 /* set when new kernel signal arrives */
|
#define SIGNALED 0x10 /* set when new kernel signal arrives */
|
||||||
#define SIG_PENDING 0x20 /* unready while signal being processed */
|
#define SIG_PENDING 0x20 /* unready while signal being processed */
|
||||||
#define P_STOP 0x40 /* set when process is being traced */
|
#define P_STOP 0x40 /* set when process is being traced */
|
||||||
|
#define NO_PRIV 0x80 /* privilege structure not yet initialized */
|
||||||
/* Bits for the other process flags. */
|
|
||||||
#define PREEMPTIBLE 0x01 /* kernel tasks are not preemptible */
|
|
||||||
#define SCHED_Q_HEAD 0x02 /* add to queue head instead of tail */
|
|
||||||
#define BILLABLE 0x04 /* system services are not billable */
|
|
||||||
|
|
||||||
/* Scheduling priorities for p_priority. Values must start at zero (highest
|
/* Scheduling priorities for p_priority. Values must start at zero (highest
|
||||||
* priority) and increment. Priorities of the processes in the boot image can
|
* priority) and increment. Priorities of the processes in the boot image can
|
||||||
|
|
|
@ -215,7 +215,6 @@ vir_bytes size;
|
||||||
int privilege;
|
int privilege;
|
||||||
{
|
{
|
||||||
/* Build descriptor for a data segment. */
|
/* Build descriptor for a data segment. */
|
||||||
|
|
||||||
sdesc(segdp, base, size);
|
sdesc(segdp, base, size);
|
||||||
segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE);
|
segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE);
|
||||||
/* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
|
/* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
|
||||||
|
|
|
@ -13,16 +13,13 @@ _PROTOTYPE( void clock_stop, (void) );
|
||||||
_PROTOTYPE( clock_t get_uptime, (void) );
|
_PROTOTYPE( clock_t get_uptime, (void) );
|
||||||
_PROTOTYPE( unsigned long read_clock, (void) );
|
_PROTOTYPE( unsigned long read_clock, (void) );
|
||||||
_PROTOTYPE( void set_timer, (struct timer *tp, clock_t t, tmr_func_t f) );
|
_PROTOTYPE( void set_timer, (struct timer *tp, clock_t t, tmr_func_t f) );
|
||||||
_PROTOTYPE( void reset_timer, (struct timer *tp) );
|
_PROTOTYPE( void reset_timer, (struct timer *tp) );
|
||||||
|
|
||||||
/* klibc.c */
|
/* klibc.c */
|
||||||
_PROTOTYPE( int katoi, (register const char *s));
|
_PROTOTYPE( int katoi, (register const char *s));
|
||||||
_PROTOTYPE( void *kmemcpy, (void *s1, const void *s2, register size_t n));
|
_PROTOTYPE( void *kmemcpy, (void *s1, const void *s2, register size_t n));
|
||||||
_PROTOTYPE( void *kmemset, (void *s, register int c, register size_t n));
|
_PROTOTYPE( void *kmemset, (void *s, register int c, register size_t n));
|
||||||
_PROTOTYPE( int kstrcmp, (register const char *s1, register const char *s2));
|
_PROTOTYPE( int kstrcmp, (register const char *s1, register const char *s2));
|
||||||
_PROTOTYPE( size_t kstrlen, (const char *s));
|
|
||||||
_PROTOTYPE( int kstrncmp,
|
|
||||||
(register const char *s1, register const char *s2, register size_t n));
|
|
||||||
_PROTOTYPE( char *kstrncpy,
|
_PROTOTYPE( char *kstrncpy,
|
||||||
(char *s1, register const char *s2, register const ssize_t n));
|
(char *s1, register const char *s2, register const ssize_t n));
|
||||||
#define karg(arg) (karg_t) (arg)
|
#define karg(arg) (karg_t) (arg)
|
||||||
|
@ -33,14 +30,16 @@ _PROTOTYPE( void main, (void) );
|
||||||
_PROTOTYPE( void prepare_shutdown, (int how) );
|
_PROTOTYPE( void prepare_shutdown, (int how) );
|
||||||
_PROTOTYPE( void stop_sequence, (struct timer *tp) );
|
_PROTOTYPE( void stop_sequence, (struct timer *tp) );
|
||||||
|
|
||||||
/* misc.c */
|
/* utility.c */
|
||||||
_PROTOTYPE( void panic, (_CONST char *s, int n) );
|
_PROTOTYPE( void panic, (_CONST char *s, int n) );
|
||||||
|
_PROTOTYPE( void safe_lock, (int c, char *v) );
|
||||||
|
_PROTOTYPE( void safe_unlock, (void) );
|
||||||
_PROTOTYPE( int alloc_bit, (bitchunk_t *map, bit_t nr_bits) );
|
_PROTOTYPE( int alloc_bit, (bitchunk_t *map, bit_t nr_bits) );
|
||||||
_PROTOTYPE( void free_bit, (bit_t nr, bitchunk_t *map, bit_t nr_bits) );
|
_PROTOTYPE( void free_bit, (bit_t nr, bitchunk_t *map, bit_t nr_bits) );
|
||||||
|
|
||||||
/* proc.c */
|
/* proc.c */
|
||||||
_PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr) );
|
_PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr) );
|
||||||
_PROTOTYPE( int lock_notify, (int dst, message *m_ptr) );
|
_PROTOTYPE( int lock_alert, (int src, int dst) );
|
||||||
_PROTOTYPE( int lock_send, (int dst, message *m_ptr) );
|
_PROTOTYPE( int lock_send, (int dst, message *m_ptr) );
|
||||||
_PROTOTYPE( void lock_ready, (struct proc *rp) );
|
_PROTOTYPE( void lock_ready, (struct proc *rp) );
|
||||||
_PROTOTYPE( void lock_sched, (struct proc *rp) );
|
_PROTOTYPE( void lock_sched, (struct proc *rp) );
|
||||||
|
@ -52,6 +51,7 @@ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds,
|
||||||
|
|
||||||
/* system.c */
|
/* system.c */
|
||||||
_PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) );
|
_PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) );
|
||||||
|
_PROTOTYPE( int init_proc, (int proc_nr, int proto_nr) );
|
||||||
_PROTOTYPE( void clear_proc, (int proc_nr) );
|
_PROTOTYPE( void clear_proc, (int proc_nr) );
|
||||||
_PROTOTYPE( phys_bytes numap_local, (int proc_nr, vir_bytes vir_addr,
|
_PROTOTYPE( phys_bytes numap_local, (int proc_nr, vir_bytes vir_addr,
|
||||||
vir_bytes bytes) );
|
vir_bytes bytes) );
|
||||||
|
|
116
kernel/system.c
116
kernel/system.c
|
@ -22,6 +22,7 @@
|
||||||
* generic_handler: interrupt handler for user-level device drivers
|
* generic_handler: interrupt handler for user-level device drivers
|
||||||
*
|
*
|
||||||
* Changes:
|
* Changes:
|
||||||
|
* Apr 25, 2005 new init_proc() function (Jorrit N. Herder)
|
||||||
* Apr 25, 2005 made mapping of call vector explicit (Jorrit N. Herder)
|
* Apr 25, 2005 made mapping of call vector explicit (Jorrit N. Herder)
|
||||||
* Oct 29, 2004 new clear_proc() function (Jorrit N. Herder)
|
* Oct 29, 2004 new clear_proc() function (Jorrit N. Herder)
|
||||||
* Oct 17, 2004 generic handler and IRQ policies (Jorrit N. Herder)
|
* Oct 17, 2004 generic handler and IRQ policies (Jorrit N. Herder)
|
||||||
|
@ -38,8 +39,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/sigcontext.h>
|
#include <sys/sigcontext.h>
|
||||||
#include <sys/svrctl.h>
|
#include <sys/svrctl.h>
|
||||||
#include <minix/callnr.h>
|
|
||||||
#include "sendmask.h"
|
|
||||||
#if (CHIP == INTEL)
|
#if (CHIP == INTEL)
|
||||||
#include <ibm/memory.h>
|
#include <ibm/memory.h>
|
||||||
#include "protect.h"
|
#include "protect.h"
|
||||||
|
@ -55,7 +54,7 @@ PUBLIC int (*call_vec[NR_SYS_CALLS])(message *m_ptr);
|
||||||
|
|
||||||
#define map(call_nr, handler) \
|
#define map(call_nr, handler) \
|
||||||
{extern int dummy[NR_SYS_CALLS > (unsigned) (call_nr) ? 1 : -1];} \
|
{extern int dummy[NR_SYS_CALLS > (unsigned) (call_nr) ? 1 : -1];} \
|
||||||
call_vec[(call_nr)] = (handler)
|
call_vec[(call_nr)] = (handler)
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( void initialize, (void));
|
FORWARD _PROTOTYPE( void initialize, (void));
|
||||||
|
|
||||||
|
@ -78,11 +77,9 @@ PUBLIC void sys_task()
|
||||||
|
|
||||||
/* Handle the request. */
|
/* Handle the request. */
|
||||||
if ((unsigned) m.m_type < NR_SYS_CALLS) {
|
if ((unsigned) m.m_type < NR_SYS_CALLS) {
|
||||||
result = (*call_vec[m.m_type])(&m); /* do system call */
|
result = (*call_vec[m.m_type])(&m); /* handle the kernel call */
|
||||||
} else if(m.NOTIFY_TYPE == KSIG_PENDING) {
|
} else if (m.m_type == NEW_KSIG) {
|
||||||
message pmm;
|
lock_alert(SYSTEM, PM_PROC_NR); /* tell PM about signal */
|
||||||
pmm.NOTIFY_TYPE = KSIG_PENDING;
|
|
||||||
lock_notify(PM_PROC_NR, &pmm);
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
kprintf("Warning, illegal SYSTASK request from %d.\n", m.m_source);
|
kprintf("Warning, illegal SYSTASK request from %d.\n", m.m_source);
|
||||||
|
@ -94,7 +91,7 @@ PUBLIC void sys_task()
|
||||||
* is known to be blocked waiting for a message.
|
* is known to be blocked waiting for a message.
|
||||||
*/
|
*/
|
||||||
if (result != EDONTREPLY) {
|
if (result != EDONTREPLY) {
|
||||||
m.m_type = result; /* report status of call */
|
m.m_type = result; /* report status of call */
|
||||||
if (OK != lock_send(m.m_source, &m)) {
|
if (OK != lock_send(m.m_source, &m)) {
|
||||||
kprintf("Warning, SYSTASK couldn't reply to request from %d\n",
|
kprintf("Warning, SYSTASK couldn't reply to request from %d\n",
|
||||||
m.m_source);
|
m.m_source);
|
||||||
|
@ -109,7 +106,7 @@ PUBLIC void sys_task()
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PRIVATE void initialize(void)
|
PRIVATE void initialize(void)
|
||||||
{
|
{
|
||||||
register struct proc *rp;
|
register struct priv *sp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Initialize IRQ handler hooks. Mark all hooks available. */
|
/* Initialize IRQ handler hooks. Mark all hooks available. */
|
||||||
|
@ -118,8 +115,8 @@ PRIVATE void initialize(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize all alarm timers for all processes. */
|
/* Initialize all alarm timers for all processes. */
|
||||||
for (rp=BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
|
for (sp=BEG_PRIV_ADDR; sp < END_PRIV_ADDR; sp++) {
|
||||||
tmr_inittimer(&(rp->p_alarm_timer));
|
tmr_inittimer(&(sp->s_alarm_timer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the call vector to a safe default handler. Some system calls
|
/* Initialize the call vector to a safe default handler. Some system calls
|
||||||
|
@ -132,23 +129,22 @@ PRIVATE void initialize(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process management. */
|
/* Process management. */
|
||||||
map(SYS_FORK, do_fork); /* informs kernel that a process has forked */
|
map(SYS_FORK, do_fork); /* a process forked a new process */
|
||||||
map(SYS_XIT, do_xit); /* informs kernel that a process has exited */
|
map(SYS_NEWMAP, do_newmap); /* set up a process memory map */
|
||||||
map(SYS_NEWMAP, do_newmap); /* allows PM to set up a process memory map */
|
map(SYS_EXEC, do_exec); /* update process after execute */
|
||||||
map(SYS_EXEC, do_exec); /* sets program counter and stack pointer after EXEC */
|
map(SYS_EXIT, do_exit); /* clean up after process exit */
|
||||||
map(SYS_TRACE, do_trace); /* request a trace operation */
|
map(SYS_TRACE, do_trace); /* request a trace operation */
|
||||||
|
|
||||||
/* Signal handling. */
|
/* Signal handling. */
|
||||||
map(SYS_KILL, do_kill); /* cause a process to be signaled */
|
map(SYS_KILL, do_kill); /* cause a process to be signaled */
|
||||||
map(SYS_GETSIG, do_getsig); /* PM checks for pending signals */
|
map(SYS_GETKSIG, do_getksig); /* PM checks for pending signals */
|
||||||
map(SYS_ENDSIG, do_endsig); /* PM finished processing signal */
|
map(SYS_ENDKSIG, do_endksig); /* PM finished processing signal */
|
||||||
map(SYS_SIGSEND, do_sigsend); /* start POSIX-style signal */
|
map(SYS_SIGSEND, do_sigsend); /* start POSIX-style signal */
|
||||||
map(SYS_SIGRETURN, do_sigreturn); /* return from POSIX-style signal */
|
map(SYS_SIGRETURN, do_sigreturn); /* return from POSIX-style signal */
|
||||||
|
|
||||||
/* Clock functionality. */
|
/* Clock functionality. */
|
||||||
map(SYS_TIMES, do_times); /* get uptime and process times */
|
map(SYS_TIMES, do_times); /* get uptime and process times */
|
||||||
map(SYS_SIGNALRM, do_signalrm); /* causes an alarm signal */
|
map(SYS_SETALARM, do_setalarm); /* schedule a synchronous alarm */
|
||||||
map(SYS_SYNCALRM, do_syncalrm); /* send a notification message */
|
|
||||||
|
|
||||||
/* Device I/O. */
|
/* Device I/O. */
|
||||||
map(SYS_IRQCTL, do_irqctl); /* interrupt control operations */
|
map(SYS_IRQCTL, do_irqctl); /* interrupt control operations */
|
||||||
|
@ -156,25 +152,60 @@ PRIVATE void initialize(void)
|
||||||
map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */
|
map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */
|
||||||
map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */
|
map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */
|
||||||
|
|
||||||
/* Server and driver control. */
|
/* System control. */
|
||||||
|
map(SYS_SETPRIORITY, do_schedctl); /* set scheduling priority */
|
||||||
map(SYS_SEGCTL, do_segctl); /* add segment and get selector */
|
map(SYS_SEGCTL, do_segctl); /* add segment and get selector */
|
||||||
map(SYS_IOPENABLE, do_iopenable); /* enable CPU I/O protection bits */
|
|
||||||
map(SYS_SVRCTL, do_svrctl); /* kernel control functions */
|
map(SYS_SVRCTL, do_svrctl); /* kernel control functions */
|
||||||
|
|
||||||
/* Copying. */
|
/* Copying. */
|
||||||
map(SYS_UMAP, do_umap); /* map virtual to physical address */
|
map(SYS_UMAP, do_umap); /* map virtual to physical address */
|
||||||
map(SYS_VIRCOPY, do_vircopy); /* use pure virtual addressing */
|
map(SYS_VIRCOPY, do_vircopy); /* use pure virtual addressing */
|
||||||
map(SYS_PHYSCOPY, do_physcopy); /* use physical addressing */
|
map(SYS_PHYSCOPY, do_physcopy); /* use physical addressing */
|
||||||
map(SYS_PHYSZERO, do_physzero); /* zero physical memory region */
|
|
||||||
map(SYS_VIRVCOPY, do_virvcopy); /* vector with copy requests */
|
map(SYS_VIRVCOPY, do_virvcopy); /* vector with copy requests */
|
||||||
map(SYS_PHYSVCOPY, do_physvcopy); /* vector with copy requests */
|
map(SYS_PHYSVCOPY, do_physvcopy); /* vector with copy requests */
|
||||||
map(SYS_SETPRIORITY, do_setpriority); /* set scheduling priority */
|
map(SYS_MEMSET, do_memset); /* write char to memory area */
|
||||||
|
|
||||||
/* Miscellaneous. */
|
/* Miscellaneous. */
|
||||||
map(SYS_ABORT, do_abort); /* abort MINIX */
|
map(SYS_ABORT, do_abort); /* abort MINIX */
|
||||||
map(SYS_GETINFO, do_getinfo); /* request system information */
|
map(SYS_GETINFO, do_getinfo); /* request system information */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* init_proc *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int init_proc(proc_nr, proto_nr)
|
||||||
|
int proc_nr; /* slot of process to initialize */
|
||||||
|
int proto_nr; /* prototype process to copy from */
|
||||||
|
{
|
||||||
|
register struct proc *rc, *rp;
|
||||||
|
register struct priv *sp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Get a pointer to the process to initialize. */
|
||||||
|
rc = proc_addr(proc_nr);
|
||||||
|
|
||||||
|
/* If there is a prototype process to initialize from, use it. Otherwise,
|
||||||
|
* assume the caller will take care of initialization, but make sure that
|
||||||
|
* the new process gets a pointer to a system properties structure.
|
||||||
|
*/
|
||||||
|
if (isokprocn(proto_nr)) {
|
||||||
|
kprintf("INIT proc from prototype %d\n", proto_nr);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
|
||||||
|
if (sp->s_proc_nr == NONE) { /* found free slot */
|
||||||
|
sp->s_proc_nr = proc_nr; /* set association */
|
||||||
|
rc->p_priv = sp; /* assign to process */
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kprintf("No free PRIV structure!\n", NO_NUM);
|
||||||
|
return(ENOSPC); /* out of resources */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* clear_proc *
|
* clear_proc *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -189,7 +220,7 @@ int proc_nr; /* slot of process to clean up */
|
||||||
rc = proc_addr(proc_nr);
|
rc = proc_addr(proc_nr);
|
||||||
|
|
||||||
/* Turn off any alarm timers at the clock. */
|
/* Turn off any alarm timers at the clock. */
|
||||||
reset_timer(&rc->p_alarm_timer);
|
reset_timer(&rc->p_priv->s_alarm_timer);
|
||||||
|
|
||||||
/* Make sure the exiting process is no longer scheduled. */
|
/* Make sure the exiting process is no longer scheduled. */
|
||||||
if (rc->p_rts_flags == 0) lock_unready(rc);
|
if (rc->p_rts_flags == 0) lock_unready(rc);
|
||||||
|
@ -232,7 +263,6 @@ int proc_nr; /* slot of process to clean up */
|
||||||
kstrncpy(rc->p_name, "<none>", P_NAME_LEN); /* unset name */
|
kstrncpy(rc->p_name, "<none>", P_NAME_LEN); /* unset name */
|
||||||
sigemptyset(&rc->p_pending); /* remove pending signals */
|
sigemptyset(&rc->p_pending); /* remove pending signals */
|
||||||
rc->p_rts_flags = SLOT_FREE; /* announce slot empty */
|
rc->p_rts_flags = SLOT_FREE; /* announce slot empty */
|
||||||
rc->p_sendmask = DENY_ALL_MASK; /* set most restrictive mask */
|
|
||||||
|
|
||||||
#if (CHIP == M68000)
|
#if (CHIP == M68000)
|
||||||
pmmu_delete(rc); /* we're done, remove tables */
|
pmmu_delete(rc); /* we're done, remove tables */
|
||||||
|
@ -260,7 +290,7 @@ PUBLIC void get_randomness()
|
||||||
* On machines without RDTSC, we use the get_uptime() - read_clock()
|
* On machines without RDTSC, we use the get_uptime() - read_clock()
|
||||||
* has a higher resolution, but would involve I/O calls.
|
* has a higher resolution, but would involve I/O calls.
|
||||||
*/
|
*/
|
||||||
if(machine.processor > 486)
|
if (machine.processor > 486)
|
||||||
read_tsc(&tsc_high, &krandom.r_buf[krandom.r_next]);
|
read_tsc(&tsc_high, &krandom.r_buf[krandom.r_next]);
|
||||||
else
|
else
|
||||||
krandom.r_buf[krandom.r_next] = get_uptime();
|
krandom.r_buf[krandom.r_next] = get_uptime();
|
||||||
|
@ -278,18 +308,21 @@ irq_hook_t *hook;
|
||||||
/* This function handles hardware interrupt in a simple and generic way. All
|
/* This function handles hardware interrupt in a simple and generic way. All
|
||||||
* interrupts are transformed into messages to a driver. The IRQ line will be
|
* interrupts are transformed into messages to a driver. The IRQ line will be
|
||||||
* reenabled if the policy says so.
|
* reenabled if the policy says so.
|
||||||
* In addition, the interrupt handler gathers random information in a buffer
|
|
||||||
* by timestamping the interrupts.
|
|
||||||
*/
|
*/
|
||||||
message m;
|
|
||||||
|
|
||||||
/* Gather random information. */
|
/* As a side-effect, the interrupt handler gathers random information by
|
||||||
|
* timestamping the interrupt events. This is used for /dev/random.
|
||||||
|
*/
|
||||||
get_randomness();
|
get_randomness();
|
||||||
|
|
||||||
|
/* Add a bit for this interrupt to the process' pending interrupts. When
|
||||||
|
* sending the notification message, this bit map will be magically set
|
||||||
|
* as an argument.
|
||||||
|
*/
|
||||||
|
priv(proc_addr(hook->proc_nr))->s_int_pending |= (1 << hook->irq);
|
||||||
|
|
||||||
/* Build notification message and return. */
|
/* Build notification message and return. */
|
||||||
m.NOTIFY_TYPE = HARD_INT;
|
lock_alert(HARDWARE, hook->proc_nr);
|
||||||
m.NOTIFY_ARG = hook->irq;
|
|
||||||
lock_notify(hook->proc_nr, &m);
|
|
||||||
return(hook->policy & IRQ_REENABLE);
|
return(hook->policy & IRQ_REENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,9 +335,9 @@ int proc_nr; /* process to be signalled */
|
||||||
int sig_nr; /* signal to be sent, 1 to _NSIG */
|
int sig_nr; /* signal to be sent, 1 to _NSIG */
|
||||||
{
|
{
|
||||||
/* A system process wants to send a signal to a process. Examples are:
|
/* A system process wants to send a signal to a process. Examples are:
|
||||||
* TTY wanting to cause SIGINT upon getting a DEL
|
* - HARDWARE wanting to cause a SIGSEGV after a CPU exception
|
||||||
* CLOCK wanting to cause SIGALRM when timer expires
|
* - TTY wanting to cause SIGINT upon getting a DEL
|
||||||
* FS wanting to cause SIGPIPE for a broken pipe
|
* - FS wanting to cause SIGPIPE for a broken pipe
|
||||||
* Signals are handled by sending a message to PM. This function handles the
|
* Signals are handled by sending a message to PM. This function handles the
|
||||||
* signals and makes sure the PM gets them by sending a notification. The
|
* signals and makes sure the PM gets them by sending a notification. The
|
||||||
* process being signaled is blocked while PM has not finished all signals
|
* process being signaled is blocked while PM has not finished all signals
|
||||||
|
@ -313,7 +346,6 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */
|
||||||
* PM can block waiting for FS to do a core dump.
|
* PM can block waiting for FS to do a core dump.
|
||||||
*/
|
*/
|
||||||
register struct proc *rp;
|
register struct proc *rp;
|
||||||
message m;
|
|
||||||
|
|
||||||
/* Check if the signal is already pending. Process it otherwise. */
|
/* Check if the signal is already pending. Process it otherwise. */
|
||||||
rp = proc_addr(proc_nr);
|
rp = proc_addr(proc_nr);
|
||||||
|
@ -322,8 +354,7 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */
|
||||||
if (! (rp->p_rts_flags & SIGNALED)) { /* other pending */
|
if (! (rp->p_rts_flags & SIGNALED)) { /* other pending */
|
||||||
if (rp->p_rts_flags == 0) lock_unready(rp); /* make not ready */
|
if (rp->p_rts_flags == 0) lock_unready(rp); /* make not ready */
|
||||||
rp->p_rts_flags |= SIGNALED | SIG_PENDING; /* update flags */
|
rp->p_rts_flags |= SIGNALED | SIG_PENDING; /* update flags */
|
||||||
m.NOTIFY_TYPE = KSIG_PENDING;
|
lock_alert(HARDWARE, SYSTEM);
|
||||||
lock_notify(SYSTASK, &m);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,7 +401,6 @@ vir_bytes vir_addr; /* virtual address in bytes within the seg */
|
||||||
vir_bytes bytes; /* # of bytes to be copied */
|
vir_bytes bytes; /* # of bytes to be copied */
|
||||||
{
|
{
|
||||||
/* Calculate the physical memory address for a given virtual address. */
|
/* Calculate the physical memory address for a given virtual address. */
|
||||||
|
|
||||||
vir_clicks vc; /* the virtual address in clicks */
|
vir_clicks vc; /* the virtual address in clicks */
|
||||||
phys_bytes pa; /* intermediate variables as phys_bytes */
|
phys_bytes pa; /* intermediate variables as phys_bytes */
|
||||||
#if (CHIP == INTEL)
|
#if (CHIP == INTEL)
|
||||||
|
@ -451,7 +481,7 @@ vir_bytes bytes; /* # of bytes to be copied */
|
||||||
if (bytes <= 0) return( (phys_bytes) 0);
|
if (bytes <= 0) return( (phys_bytes) 0);
|
||||||
if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
|
if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
|
||||||
|
|
||||||
fm = &rp->p_farmem[seg];
|
fm = &rp->p_priv->s_farmem[seg];
|
||||||
if (! fm->in_use) return( (phys_bytes) 0);
|
if (! fm->in_use) return( (phys_bytes) 0);
|
||||||
if (vir_addr + bytes > fm->mem_len) return( (phys_bytes) 0);
|
if (vir_addr + bytes > fm->mem_len) return( (phys_bytes) 0);
|
||||||
|
|
||||||
|
|
149
kernel/system.h
149
kernel/system.h
|
@ -1,60 +1,151 @@
|
||||||
/* Function prototypes for the system library. The implementation is contained
|
/* Function prototypes for the system library. The prototypes in this file
|
||||||
* in src/kernel/system/. The system library allows to access system services
|
* are undefined to do_unused if the kernel call is not enabled in config.h.
|
||||||
* by doing a system call. System calls are transformed into request messages
|
* The implementation is contained in src/kernel/system/.
|
||||||
* to the SYS task that is responsible for handling the call. By convention, a
|
*
|
||||||
* sys_call() is transformed into a message with type SYS_CALL that is handled
|
* The system library allows to access system services by doing a system call.
|
||||||
* in a function named do_call().
|
* System calls are transformed into request messages to the SYS task that is
|
||||||
|
* responsible for handling the call. By convention, sys_call() is transformed
|
||||||
|
* into a message with type SYS_CALL that is handled in a function do_call().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SYSTEM_H
|
#ifndef SYSTEM_H
|
||||||
#define SYSTEM_H
|
#define SYSTEM_H
|
||||||
|
|
||||||
/* Common includes for the system library. */
|
/* Common includes for the system library. */
|
||||||
#include <minix/com.h>
|
#include "kernel.h"
|
||||||
#include <minix/config.h>
|
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
|
|
||||||
_PROTOTYPE( int do_exec, (message *m_ptr) ); /* process control */
|
/* Default handler for unused kernel calls. */
|
||||||
_PROTOTYPE( int do_fork, (message *m_ptr) );
|
_PROTOTYPE( int do_unused, (message *m_ptr) );
|
||||||
_PROTOTYPE( int do_newmap, (message *m_ptr) );
|
|
||||||
_PROTOTYPE( int do_xit, (message *m_ptr) );
|
|
||||||
|
|
||||||
_PROTOTYPE( int do_copy, (message *m_ptr) ); /* copying */
|
_PROTOTYPE( int do_exec, (message *m_ptr) );
|
||||||
|
#if ! USE_EXEC
|
||||||
|
#define do_exec do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_fork, (message *m_ptr) );
|
||||||
|
#if ! USE_FORK
|
||||||
|
#define do_fork do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_newmap, (message *m_ptr) );
|
||||||
|
#if ! USE_NEWMAP
|
||||||
|
#define do_newmap do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_exit, (message *m_ptr) );
|
||||||
|
#if ! USE_EXIT
|
||||||
|
#define do_exit do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_trace, (message *m_ptr) );
|
||||||
|
#if ! USE_TRACE
|
||||||
|
#define do_trace do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_schedctl, (message *m_ptr) );
|
||||||
|
#if ! USE_SCHEDCTL
|
||||||
|
#define do_schedctl do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_copy, (message *m_ptr) );
|
||||||
#define do_vircopy do_copy
|
#define do_vircopy do_copy
|
||||||
#define do_physcopy do_copy
|
#define do_physcopy do_copy
|
||||||
|
#if ! (USE_VIRCOPY || USE_PHYSCOPY)
|
||||||
|
#define do_copy do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_vcopy, (message *m_ptr) );
|
_PROTOTYPE( int do_vcopy, (message *m_ptr) );
|
||||||
#define do_virvcopy do_vcopy
|
#define do_virvcopy do_vcopy
|
||||||
#define do_physvcopy do_vcopy
|
#define do_physvcopy do_vcopy
|
||||||
|
#if ! (USE_VIRVCOPY || USE_PHYSVCOPY)
|
||||||
|
#define do_vcopy do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_umap, (message *m_ptr) );
|
_PROTOTYPE( int do_umap, (message *m_ptr) );
|
||||||
_PROTOTYPE( int do_physzero, (message *m_ptr) );
|
#if ! USE_UMAP
|
||||||
|
#define do_umap do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_memset, (message *m_ptr) );
|
||||||
|
#if ! USE_MEMSET
|
||||||
|
#define do_memset do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_unused, (message *m_ptr) ); /* miscellaneous */
|
|
||||||
_PROTOTYPE( int do_abort, (message *m_ptr) );
|
_PROTOTYPE( int do_abort, (message *m_ptr) );
|
||||||
|
#if ! USE_ABORT
|
||||||
|
#define do_abort do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_getinfo, (message *m_ptr) );
|
_PROTOTYPE( int do_getinfo, (message *m_ptr) );
|
||||||
|
#if ! USE_GETINFO
|
||||||
|
#define do_getinfo do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_svrctl, (message *m_ptr) );
|
||||||
|
#if ! USE_SVRCTL
|
||||||
|
#define do_svrctl do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_svrctl, (message *m_ptr) ); /* system control */
|
|
||||||
_PROTOTYPE( int do_iopenable, (message *m_ptr) );
|
|
||||||
_PROTOTYPE( int do_segctl, (message *m_ptr) );
|
_PROTOTYPE( int do_segctl, (message *m_ptr) );
|
||||||
|
#if ! USE_SEGCTL
|
||||||
|
#define do_segctl do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_irqctl, (message *m_ptr) );
|
||||||
|
#if ! USE_IRQCTL
|
||||||
|
#define do_irqctl do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_irqctl, (message *m_ptr) ); /* device I/O */
|
|
||||||
_PROTOTYPE( int do_devio, (message *m_ptr) );
|
_PROTOTYPE( int do_devio, (message *m_ptr) );
|
||||||
|
#if ! USE_DEVIO
|
||||||
|
#define do_devio do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_vdevio, (message *m_ptr) );
|
_PROTOTYPE( int do_vdevio, (message *m_ptr) );
|
||||||
|
#if ! USE_VDEVIO
|
||||||
|
#define do_vdevio do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_sdevio, (message *m_ptr) );
|
_PROTOTYPE( int do_sdevio, (message *m_ptr) );
|
||||||
|
#if ! USE_SDEVIO
|
||||||
|
#define do_sdevio do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_kill, (message *m_ptr) );
|
||||||
|
#if ! USE_KILL
|
||||||
|
#define do_kill do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_getksig, (message *m_ptr) );
|
||||||
|
#if ! USE_GETKSIG
|
||||||
|
#define do_getksig do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_endksig, (message *m_ptr) );
|
||||||
|
#if ! USE_ENDKSIG
|
||||||
|
#define do_endksig do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_kill, (message *m_ptr) ); /* signal handling */
|
|
||||||
_PROTOTYPE( int do_getsig, (message *m_ptr) );
|
|
||||||
_PROTOTYPE( int do_endsig, (message *m_ptr) );
|
|
||||||
_PROTOTYPE( int do_sigsend, (message *m_ptr) );
|
_PROTOTYPE( int do_sigsend, (message *m_ptr) );
|
||||||
|
#if ! USE_SIGSEND
|
||||||
|
#define do_sigsend do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_sigreturn, (message *m_ptr) );
|
_PROTOTYPE( int do_sigreturn, (message *m_ptr) );
|
||||||
_PROTOTYPE( int do_setpriority, (message *m_ptr) );
|
#if ! USE_SIGRETURN
|
||||||
|
#define do_sigreturn do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_PROTOTYPE( int do_times, (message *m_ptr) );
|
||||||
|
#if ! USE_TIMES
|
||||||
|
#define do_times do_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_times, (message *m_ptr) ); /* clock functions */
|
|
||||||
_PROTOTYPE( int do_setalarm, (message *m_ptr) );
|
_PROTOTYPE( int do_setalarm, (message *m_ptr) );
|
||||||
#define do_flagalrm do_setalarm
|
#if ! USE_SETALARM
|
||||||
#define do_signalrm do_setalarm
|
#define do_setalarm do_unused
|
||||||
#define do_syncalrm do_setalarm
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE( int do_trace, (message *m_ptr) ); /* process tracing */
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* SYSTEM_H */
|
#endif /* SYSTEM_H */
|
||||||
|
|
||||||
|
|
|
@ -5,20 +5,50 @@ u = /usr
|
||||||
i = $u/include
|
i = $u/include
|
||||||
|
|
||||||
# Programs, flags, etc.
|
# Programs, flags, etc.
|
||||||
CC = exec cc
|
CC = exec cc $(CFLAGS) -c
|
||||||
CPP = $l/cpp
|
CPP = $l/cpp
|
||||||
LD = $(CC) -.o
|
LD = $(CC) -.o
|
||||||
CFLAGS = -I$i
|
CFLAGS = -I$i
|
||||||
LDFLAGS = -i
|
LDFLAGS = -i
|
||||||
|
|
||||||
SYS = clock.o copying.o debugging.o devio.o irqctl.o proctl.o \
|
SYSTEM = ../system.a
|
||||||
sysctl.o misc.o sigctl.o tracing.o priority.o
|
|
||||||
|
|
||||||
# What to make.
|
# What to make.
|
||||||
all build: $(SYS)
|
all build install: $(SYSTEM)
|
||||||
|
|
||||||
|
OBJECTS = \
|
||||||
|
$(SYSTEM)(do_unused.o) \
|
||||||
|
$(SYSTEM)(do_fork.o) \
|
||||||
|
$(SYSTEM)(do_exec.o) \
|
||||||
|
$(SYSTEM)(do_newmap.o) \
|
||||||
|
$(SYSTEM)(do_exit.o) \
|
||||||
|
$(SYSTEM)(do_trace.o) \
|
||||||
|
$(SYSTEM)(do_schedctl.o) \
|
||||||
|
$(SYSTEM)(do_times.o) \
|
||||||
|
$(SYSTEM)(do_alarm.o) \
|
||||||
|
$(SYSTEM)(do_irqctl.o) \
|
||||||
|
$(SYSTEM)(do_devio.o) \
|
||||||
|
$(SYSTEM)(do_vdevio.o) \
|
||||||
|
$(SYSTEM)(do_sdevio.o) \
|
||||||
|
$(SYSTEM)(do_copy.o) \
|
||||||
|
$(SYSTEM)(do_vcopy.o) \
|
||||||
|
$(SYSTEM)(do_umap.o) \
|
||||||
|
$(SYSTEM)(do_memset.o) \
|
||||||
|
$(SYSTEM)(do_svrctl.o) \
|
||||||
|
$(SYSTEM)(do_segctl.o) \
|
||||||
|
$(SYSTEM)(do_getksig.o) \
|
||||||
|
$(SYSTEM)(do_endksig.o) \
|
||||||
|
$(SYSTEM)(do_kill.o) \
|
||||||
|
$(SYSTEM)(do_sigsend.o) \
|
||||||
|
$(SYSTEM)(do_sigreturn.o) \
|
||||||
|
$(SYSTEM)(do_abort.o) \
|
||||||
|
$(SYSTEM)(do_getinfo.o) \
|
||||||
|
|
||||||
|
$(SYSTEM): $(OBJECTS)
|
||||||
|
aal cr $@ *.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.a *.o *.bak
|
rm -f $(SYSTEM) *.o *.bak
|
||||||
|
|
||||||
depend:
|
depend:
|
||||||
/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
|
/usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
|
||||||
|
@ -27,4 +57,81 @@ depend:
|
||||||
include .depend
|
include .depend
|
||||||
|
|
||||||
|
|
||||||
|
$(SYSTEM)(do_unused.o): do_unused.c
|
||||||
|
$(CC) do_unused.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_fork.o): do_fork.c
|
||||||
|
$(CC) do_fork.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_exec.o): do_exec.c
|
||||||
|
$(CC) do_exec.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_newmap.o): do_newmap.c
|
||||||
|
$(CC) do_newmap.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_exit.o): do_exit.c
|
||||||
|
$(CC) do_exit.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_trace.o): do_trace.c
|
||||||
|
$(CC) do_trace.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_schedctl.o): do_schedctl.c
|
||||||
|
$(CC) do_schedctl.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_times.o): do_times.c
|
||||||
|
$(CC) do_times.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_alarm.o): do_alarm.c
|
||||||
|
$(CC) do_alarm.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_irqctl.o): do_irqctl.c
|
||||||
|
$(CC) do_irqctl.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_devio.o): do_devio.c
|
||||||
|
$(CC) do_devio.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_sdevio.o): do_sdevio.c
|
||||||
|
$(CC) do_sdevio.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_vdevio.o): do_vdevio.c
|
||||||
|
$(CC) do_vdevio.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_copy.o): do_copy.c
|
||||||
|
$(CC) do_copy.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_vcopy.o): do_vcopy.c
|
||||||
|
$(CC) do_vcopy.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_umap.o): do_umap.c
|
||||||
|
$(CC) do_umap.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_memset.o): do_memset.c
|
||||||
|
$(CC) do_memset.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_getksig.o): do_getksig.c
|
||||||
|
$(CC) do_getksig.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_endksig.o): do_endksig.c
|
||||||
|
$(CC) do_endksig.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_kill.o): do_kill.c
|
||||||
|
$(CC) do_kill.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_sigsend.o): do_sigsend.c
|
||||||
|
$(CC) do_sigsend.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_sigreturn.o): do_sigreturn.c
|
||||||
|
$(CC) do_sigreturn.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_getinfo.o): do_getinfo.c
|
||||||
|
$(CC) do_getinfo.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_abort.o): do_abort.c
|
||||||
|
$(CC) do_abort.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_svrctl.o): do_svrctl.c
|
||||||
|
$(CC) do_svrctl.c
|
||||||
|
|
||||||
|
$(SYSTEM)(do_segctl.o): do_segctl.c
|
||||||
|
$(CC) do_segctl.c
|
||||||
|
|
||||||
|
|
|
@ -1,138 +0,0 @@
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_TIMES
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m4_l1: T_PROC_NR (get info for this process)
|
|
||||||
* m4_l1: T_USER_TIME (return values ...)
|
|
||||||
* m4_l2: T_SYSTEM_TIME
|
|
||||||
* m4_l5: T_BOOT_TICKS
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../system.h"
|
|
||||||
#include "../debug.h"
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_times *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_times(m_ptr)
|
|
||||||
register message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Handle sys_times(). Retrieve the accounting information. */
|
|
||||||
|
|
||||||
register struct proc *rp;
|
|
||||||
int proc_nr;
|
|
||||||
|
|
||||||
/* Insert the times needed by the SYS_TIMES system call in the message. */
|
|
||||||
proc_nr = (m_ptr->T_PROC_NR == SELF) ? m_ptr->m_source : m_ptr->T_PROC_NR;
|
|
||||||
if (isokprocn(proc_nr)) {
|
|
||||||
rp = proc_addr(m_ptr->T_PROC_NR);
|
|
||||||
lock(11, "do_times"); /* halt the volatile time counters in rp */
|
|
||||||
m_ptr->T_USER_TIME = rp->p_user_time;
|
|
||||||
m_ptr->T_SYSTEM_TIME = rp->p_sys_time;
|
|
||||||
unlock(11);
|
|
||||||
}
|
|
||||||
m_ptr->T_BOOT_TICKS = get_uptime();
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_SIGNALRM, SYS_SYNCALRM
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m2_i1: ALRM_PROC_NR (set alarm for this process)
|
|
||||||
* m2_l1: ALRM_EXP_TIME (alarm's expiration time)
|
|
||||||
* m2_i2: ALRM_ABS_TIME (expiration time is absolute?)
|
|
||||||
* m2_l1: ALRM_SEC_LEFT (return seconds left of previous)
|
|
||||||
*
|
|
||||||
* Changes:
|
|
||||||
* Aug 25, 2004 fully rewritten to clean up code (Jorrit N. Herder)
|
|
||||||
*/
|
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( void cause_syncalrm, (timer_t *tp) );
|
|
||||||
FORWARD _PROTOTYPE( void cause_signalrm, (timer_t *tp) );
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_setalarm *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_setalarm(m_ptr)
|
|
||||||
message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* A process requests an alarm, or wants to cancel its alarm. This function
|
|
||||||
* is shared used for both the SYS_SIGNALRM and SYS_SYNCALRM.
|
|
||||||
*/
|
|
||||||
int proc_nr; /* which process wants the alarm */
|
|
||||||
long exp_time; /* expiration time for this alarm */
|
|
||||||
int use_abs_time; /* use absolute or relative time */
|
|
||||||
timer_t *tp; /* the process' timer structure */
|
|
||||||
clock_t uptime; /* placeholder for current uptime */
|
|
||||||
|
|
||||||
/* Extract shared parameters from the request message. */
|
|
||||||
proc_nr = m_ptr->ALRM_PROC_NR; /* process to interrupt later */
|
|
||||||
if (SELF == proc_nr) proc_nr = m_ptr->m_source;
|
|
||||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
|
||||||
exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */
|
|
||||||
use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */
|
|
||||||
|
|
||||||
/* Get the timer structure and set the parameters for this alarm. */
|
|
||||||
tp = &(proc_addr(proc_nr)->p_alarm_timer);
|
|
||||||
tmr_arg(tp)->ta_int = proc_nr;
|
|
||||||
switch (m_ptr->m_type) {
|
|
||||||
case SYS_SYNCALRM: tp->tmr_func = cause_syncalrm; break;
|
|
||||||
case SYS_SIGNALRM: tp->tmr_func = cause_signalrm; break;
|
|
||||||
default: return(EINVAL); /* invalid alarm type */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the ticks left on the previous alarm. */
|
|
||||||
uptime = get_uptime();
|
|
||||||
if ((tp->tmr_exp_time == TMR_NEVER) || (tp->tmr_exp_time < uptime) ) {
|
|
||||||
m_ptr->ALRM_TIME_LEFT = 0;
|
|
||||||
} else {
|
|
||||||
m_ptr->ALRM_TIME_LEFT = (tp->tmr_exp_time - uptime);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally, (re)set the timer depending on 'exp_time'. */
|
|
||||||
if (exp_time == 0) {
|
|
||||||
reset_timer(tp);
|
|
||||||
} else {
|
|
||||||
tp->tmr_exp_time = (use_abs_time) ? exp_time : exp_time + get_uptime();
|
|
||||||
set_timer(tp, tp->tmr_exp_time, tp->tmr_func);
|
|
||||||
}
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* cause_signalrm *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE void cause_signalrm(tp)
|
|
||||||
timer_t *tp;
|
|
||||||
{
|
|
||||||
/* Routine called if a timer goes off for a process that requested an SIGALRM
|
|
||||||
* signal using the alarm(2) system call. The timer argument 'ta_int' contains
|
|
||||||
* the process number of the process to signal.
|
|
||||||
*/
|
|
||||||
cause_sig(tmr_arg(tp)->ta_int, SIGALRM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* cause_syncalrm *
|
|
||||||
*===========================================================================*/
|
|
||||||
PRIVATE void cause_syncalrm(tp)
|
|
||||||
timer_t *tp;
|
|
||||||
{
|
|
||||||
/* Routine called if a timer goes off and the process requested a synchronous
|
|
||||||
* alarm. The process number is stored in timer argument 'ta_int'. Notify that
|
|
||||||
* process given with a SYN_ALARM message.
|
|
||||||
*/
|
|
||||||
message m;
|
|
||||||
m.NOTIFY_TYPE = SYN_ALARM;
|
|
||||||
m.NOTIFY_ARG = get_uptime();
|
|
||||||
m.NOTIFY_FLAGS = 0;
|
|
||||||
lock_notify(tmr_arg(tp)->ta_int, &m);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,176 +0,0 @@
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_VIRCOPY, SYS_PHYSCOPY, SYS_PHYSZERO
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m5_c1: CP_SRC_SPACE
|
|
||||||
* m5_l1: CP_SRC_ADDR
|
|
||||||
* m5_i1: CP_SRC_PROC_NR
|
|
||||||
* m5_c2: CP_DST_SPACE
|
|
||||||
* m5_l2: CP_DST_ADDR
|
|
||||||
* m5_i2: CP_DST_PROC_NR
|
|
||||||
* m5_l3: CP_NR_BYTES
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../system.h"
|
|
||||||
#include <minix/type.h>
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_copy *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_copy(m_ptr)
|
|
||||||
register message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or
|
|
||||||
* physical addressing.
|
|
||||||
*/
|
|
||||||
struct vir_addr vir_addr[2]; /* virtual source and destination address */
|
|
||||||
vir_bytes bytes; /* number of bytes to copy */
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Dismember the command message. */
|
|
||||||
vir_addr[_SRC_].proc_nr = m_ptr->CP_SRC_PROC_NR;
|
|
||||||
vir_addr[_SRC_].segment = m_ptr->CP_SRC_SPACE;
|
|
||||||
vir_addr[_SRC_].offset = (vir_bytes) m_ptr->CP_SRC_ADDR;
|
|
||||||
vir_addr[_DST_].proc_nr = m_ptr->CP_DST_PROC_NR;
|
|
||||||
vir_addr[_DST_].segment = m_ptr->CP_DST_SPACE;
|
|
||||||
vir_addr[_DST_].offset = (vir_bytes) m_ptr->CP_DST_ADDR;
|
|
||||||
bytes = (phys_bytes) m_ptr->CP_NR_BYTES;
|
|
||||||
|
|
||||||
/* Now do some checks for both the source and destination virtual address.
|
|
||||||
* This is done once for _SRC_, then once for _DST_.
|
|
||||||
*/
|
|
||||||
for (i=_SRC_; i<=_DST_; i++) {
|
|
||||||
|
|
||||||
/* Check if process number was given implictly with SELF and is valid. */
|
|
||||||
if (vir_addr[i].proc_nr == SELF) vir_addr[i].proc_nr = m_ptr->m_source;
|
|
||||||
if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG) {
|
|
||||||
kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_NUM);
|
|
||||||
return(EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if physical addressing is used without SYS_PHYSCOPY. */
|
|
||||||
if ((vir_addr[i].segment & PHYS_SEG) &&
|
|
||||||
m_ptr->m_type != SYS_PHYSCOPY) return(EPERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for overflow. This would happen for 64K segments and 16-bit
|
|
||||||
* vir_bytes. Especially copying by the PM on do_fork() is affected.
|
|
||||||
*/
|
|
||||||
if (bytes != (vir_bytes) bytes) {
|
|
||||||
kprintf("do_vircopy: overflow\n", NO_NUM);
|
|
||||||
return(E2BIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now try to make the actual virtual copy. */
|
|
||||||
return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Buffer to hold copy request vector from user. */
|
|
||||||
PRIVATE struct vir_cp_req vir_cp_req[VCOPY_VEC_SIZE];
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_vcopy *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_vcopy(m_ptr)
|
|
||||||
register message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Handle sys_virvcopy(). Handle virtual copy requests from vector. */
|
|
||||||
int nr_req;
|
|
||||||
int caller_pid;
|
|
||||||
vir_bytes caller_vir;
|
|
||||||
phys_bytes caller_phys;
|
|
||||||
phys_bytes kernel_phys;
|
|
||||||
phys_bytes bytes;
|
|
||||||
int i,s;
|
|
||||||
struct vir_cp_req *req;
|
|
||||||
|
|
||||||
/* Check if request vector size is ok. */
|
|
||||||
nr_req = (unsigned) m_ptr->VCP_VEC_SIZE;
|
|
||||||
if (nr_req > VCOPY_VEC_SIZE) return(EINVAL);
|
|
||||||
bytes = nr_req * sizeof(struct vir_cp_req);
|
|
||||||
|
|
||||||
/* Calculate physical addresses and copy (port,value)-pairs from user. */
|
|
||||||
caller_pid = (int) m_ptr->m_source;
|
|
||||||
caller_vir = (vir_bytes) m_ptr->VCP_VEC_ADDR;
|
|
||||||
caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes);
|
|
||||||
if (0 == caller_phys) return(EFAULT);
|
|
||||||
kernel_phys = vir2phys(vir_cp_req);
|
|
||||||
phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
|
|
||||||
|
|
||||||
/* Assume vector with requests is correct. Try to copy everything. */
|
|
||||||
for (i=0; i<nr_req; i++) {
|
|
||||||
|
|
||||||
req = &vir_cp_req[i];
|
|
||||||
|
|
||||||
/* Check if physical addressing is used without SYS_PHYSVCOPY. */
|
|
||||||
if (((req->src.segment | req->dst.segment) & PHYS_SEG) &&
|
|
||||||
m_ptr->m_type != SYS_PHYSVCOPY)
|
|
||||||
return(EPERM);
|
|
||||||
if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK)
|
|
||||||
return(s);
|
|
||||||
}
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_physzero *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_physzero(m_ptr)
|
|
||||||
register message *m_ptr;
|
|
||||||
{
|
|
||||||
/* Handle sys_physzero(). */
|
|
||||||
phys_zero((phys_bytes) m_ptr->PZ_MEM_PTR, (phys_bytes) m_ptr->PZ_COUNT);
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_UMAP
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m5_i1: CP_SRC_PROC_NR (process number)
|
|
||||||
* m5_c1: CP_SRC_SPACE (segment where address is: T, D, or S)
|
|
||||||
* m5_l1: CP_SRC_ADDR (virtual address)
|
|
||||||
* m5_l2: CP_DST_ADDR (returns physical address)
|
|
||||||
* m5_l3: CP_NR_BYTES (size of datastructure)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*==========================================================================*
|
|
||||||
* do_umap *
|
|
||||||
*==========================================================================*/
|
|
||||||
PUBLIC int do_umap(m_ptr)
|
|
||||||
register message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Map virtual address to physical, for non-kernel processes. */
|
|
||||||
int seg_type = m_ptr->CP_SRC_SPACE & SEGMENT_TYPE;
|
|
||||||
int seg_index = m_ptr->CP_SRC_SPACE & SEGMENT_INDEX;
|
|
||||||
vir_bytes offset = m_ptr->CP_SRC_ADDR;
|
|
||||||
int count = m_ptr->CP_NR_BYTES;
|
|
||||||
int proc_nr = (int) m_ptr->CP_SRC_PROC_NR;
|
|
||||||
phys_bytes phys_addr;
|
|
||||||
|
|
||||||
/* Verify process number. */
|
|
||||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
|
||||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
|
||||||
|
|
||||||
/* See which mapping should be made. */
|
|
||||||
switch(seg_type) {
|
|
||||||
case LOCAL_SEG:
|
|
||||||
phys_addr = umap_local(proc_addr(proc_nr), seg_index, offset, count);
|
|
||||||
break;
|
|
||||||
case REMOTE_SEG:
|
|
||||||
phys_addr = umap_remote(proc_addr(proc_nr), seg_index, offset, count);
|
|
||||||
break;
|
|
||||||
case BIOS_SEG:
|
|
||||||
phys_addr = umap_bios(proc_addr(proc_nr), offset, count);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return(EINVAL);
|
|
||||||
}
|
|
||||||
m_ptr->CP_DST_ADDR = phys_addr;
|
|
||||||
return (phys_addr == 0) ? EFAULT: OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
46
kernel/system/do_abort.c
Normal file
46
kernel/system/do_abort.c
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include "../system.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_ABORT
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m1_i1: ABRT_HOW (how to abort, possibly fetch monitor params)
|
||||||
|
* m1_i2: ABRT_MON_PROC (proc nr to get monitor params from)
|
||||||
|
* m1_i3: ABRT_MON_LEN (length of monitor params)
|
||||||
|
* m1_p1: ABRT_MON_ADDR (virtual address of params)
|
||||||
|
*/
|
||||||
|
#if USE_ABORT
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_abort *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_abort(m_ptr)
|
||||||
|
message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Handle sys_abort. MINIX is unable to continue. This can originate in the
|
||||||
|
* PM (normal abort or panic) or FS (panic), or TTY (user issued CTRL-ALT-DEL
|
||||||
|
* or ESC after debugging dumps).
|
||||||
|
*/
|
||||||
|
int how = m_ptr->ABRT_HOW;
|
||||||
|
|
||||||
|
if (how == RBT_MONITOR) {
|
||||||
|
/* The monitor is to run the specified instructions. */
|
||||||
|
int proc_nr = m_ptr->ABRT_MON_PROC;
|
||||||
|
int length = m_ptr->ABRT_MON_LEN + 1;
|
||||||
|
vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR;
|
||||||
|
phys_bytes src_phys = numap_local(proc_nr, src_vir, length);
|
||||||
|
|
||||||
|
/* Validate length and address of shutdown code before copying. */
|
||||||
|
if (length > kinfo.params_size || src_phys == 0)
|
||||||
|
phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
|
||||||
|
else
|
||||||
|
phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
|
||||||
|
}
|
||||||
|
prepare_shutdown(how);
|
||||||
|
return(OK); /* pro-forma (really EDISASTER) */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_ABORT */
|
||||||
|
|
77
kernel/system/do_alarm.c
Normal file
77
kernel/system/do_alarm.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_SETALARM
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m2_i1: ALRM_PROC_NR (set alarm for this process)
|
||||||
|
* m2_l1: ALRM_EXP_TIME (alarm's expiration time)
|
||||||
|
* m2_i2: ALRM_ABS_TIME (expiration time is absolute?)
|
||||||
|
* m2_l1: ALRM_SEC_LEFT (return seconds left of previous)
|
||||||
|
*
|
||||||
|
* Changes:
|
||||||
|
* Aug 25, 2004 fully rewritten to clean up code (Jorrit N. Herder)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
|
||||||
|
#if USE_SETALARM
|
||||||
|
|
||||||
|
FORWARD _PROTOTYPE( void cause_alarm, (timer_t *tp) );
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_setalarm *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_setalarm(m_ptr)
|
||||||
|
message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* A process requests a synchronous alarm, or wants to cancel its alarm. */
|
||||||
|
int proc_nr; /* which process wants the alarm */
|
||||||
|
long exp_time; /* expiration time for this alarm */
|
||||||
|
int use_abs_time; /* use absolute or relative time */
|
||||||
|
timer_t *tp; /* the process' timer structure */
|
||||||
|
clock_t uptime; /* placeholder for current uptime */
|
||||||
|
|
||||||
|
/* Extract shared parameters from the request message. */
|
||||||
|
proc_nr = m_ptr->ALRM_PROC_NR; /* process to interrupt later */
|
||||||
|
if (SELF == proc_nr) proc_nr = m_ptr->m_source;
|
||||||
|
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||||
|
exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */
|
||||||
|
use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */
|
||||||
|
|
||||||
|
/* Get the timer structure and set the parameters for this alarm. */
|
||||||
|
tp = &(proc_addr(proc_nr)->p_priv->s_alarm_timer);
|
||||||
|
tmr_arg(tp)->ta_int = proc_nr;
|
||||||
|
tp->tmr_func = cause_alarm;
|
||||||
|
|
||||||
|
/* Return the ticks left on the previous alarm. */
|
||||||
|
uptime = get_uptime();
|
||||||
|
if ((tp->tmr_exp_time == TMR_NEVER) || (tp->tmr_exp_time < uptime) ) {
|
||||||
|
m_ptr->ALRM_TIME_LEFT = 0;
|
||||||
|
} else {
|
||||||
|
m_ptr->ALRM_TIME_LEFT = (tp->tmr_exp_time - uptime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, (re)set the timer depending on 'exp_time'. */
|
||||||
|
if (exp_time == 0) {
|
||||||
|
reset_timer(tp);
|
||||||
|
} else {
|
||||||
|
tp->tmr_exp_time = (use_abs_time) ? exp_time : exp_time + get_uptime();
|
||||||
|
set_timer(tp, tp->tmr_exp_time, tp->tmr_func);
|
||||||
|
}
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* cause_alarm *
|
||||||
|
*===========================================================================*/
|
||||||
|
PRIVATE void cause_alarm(tp)
|
||||||
|
timer_t *tp;
|
||||||
|
{
|
||||||
|
/* Routine called if a timer goes off and the process requested a synchronous
|
||||||
|
* alarm. The process number is stored in timer argument 'ta_int'. Notify that
|
||||||
|
* process given with a SYN_ALARM message.
|
||||||
|
*/
|
||||||
|
lock_alert(CLOCK, tmr_arg(tp)->ta_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_SETALARM */
|
71
kernel/system/do_copy.c
Normal file
71
kernel/system/do_copy.c
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_VIRCOPY, SYS_PHYSCOPY
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m5_c1: CP_SRC_SPACE
|
||||||
|
* m5_l1: CP_SRC_ADDR
|
||||||
|
* m5_i1: CP_SRC_PROC_NR
|
||||||
|
* m5_c2: CP_DST_SPACE
|
||||||
|
* m5_l2: CP_DST_ADDR
|
||||||
|
* m5_i2: CP_DST_PROC_NR
|
||||||
|
* m5_l3: CP_NR_BYTES
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <minix/type.h>
|
||||||
|
|
||||||
|
#if (USE_VIRCOPY || USE_PHYSCOPY)
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_copy *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_copy(m_ptr)
|
||||||
|
register message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or
|
||||||
|
* physical addressing.
|
||||||
|
*/
|
||||||
|
struct vir_addr vir_addr[2]; /* virtual source and destination address */
|
||||||
|
vir_bytes bytes; /* number of bytes to copy */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Dismember the command message. */
|
||||||
|
vir_addr[_SRC_].proc_nr = m_ptr->CP_SRC_PROC_NR;
|
||||||
|
vir_addr[_SRC_].segment = m_ptr->CP_SRC_SPACE;
|
||||||
|
vir_addr[_SRC_].offset = (vir_bytes) m_ptr->CP_SRC_ADDR;
|
||||||
|
vir_addr[_DST_].proc_nr = m_ptr->CP_DST_PROC_NR;
|
||||||
|
vir_addr[_DST_].segment = m_ptr->CP_DST_SPACE;
|
||||||
|
vir_addr[_DST_].offset = (vir_bytes) m_ptr->CP_DST_ADDR;
|
||||||
|
bytes = (phys_bytes) m_ptr->CP_NR_BYTES;
|
||||||
|
|
||||||
|
/* Now do some checks for both the source and destination virtual address.
|
||||||
|
* This is done once for _SRC_, then once for _DST_.
|
||||||
|
*/
|
||||||
|
for (i=_SRC_; i<=_DST_; i++) {
|
||||||
|
|
||||||
|
/* Check if process number was given implictly with SELF and is valid. */
|
||||||
|
if (vir_addr[i].proc_nr == SELF) vir_addr[i].proc_nr = m_ptr->m_source;
|
||||||
|
if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG) {
|
||||||
|
kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_NUM);
|
||||||
|
return(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if physical addressing is used without SYS_PHYSCOPY. */
|
||||||
|
if ((vir_addr[i].segment & PHYS_SEG) &&
|
||||||
|
m_ptr->m_type != SYS_PHYSCOPY) return(EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for overflow. This would happen for 64K segments and 16-bit
|
||||||
|
* vir_bytes. Especially copying by the PM on do_fork() is affected.
|
||||||
|
*/
|
||||||
|
if (bytes != (vir_bytes) bytes) {
|
||||||
|
kprintf("do_vircopy: overflow\n", NO_NUM);
|
||||||
|
return(E2BIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now try to make the actual virtual copy. */
|
||||||
|
return( virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes) );
|
||||||
|
}
|
||||||
|
#endif /* (USE_VIRCOPY || USE_PHYSCOPY) */
|
||||||
|
|
||||||
|
|
44
kernel/system/do_devio.c
Normal file
44
kernel/system/do_devio.c
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_DEVIO
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m2_i3: DIO_REQUEST (request input or output)
|
||||||
|
* m2_i1: DIO_TYPE (flag indicating byte, word, or long)
|
||||||
|
* m2_l1: DIO_PORT (port to read/ write)
|
||||||
|
* m2_l2: DIO_VALUE (value to write/ return value read)
|
||||||
|
*
|
||||||
|
* Author:
|
||||||
|
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <minix/devio.h>
|
||||||
|
|
||||||
|
#if USE_DEVIO
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_devio *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_devio(m_ptr)
|
||||||
|
register message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Perform actual device I/O for byte, word, and long values. */
|
||||||
|
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
|
||||||
|
switch (m_ptr->DIO_TYPE) {
|
||||||
|
case DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break;
|
||||||
|
case DIO_WORD: m_ptr->DIO_VALUE = inw(m_ptr->DIO_PORT); break;
|
||||||
|
case DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break;
|
||||||
|
default: return(EINVAL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (m_ptr->DIO_TYPE) {
|
||||||
|
case DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||||
|
case DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||||
|
case DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
||||||
|
default: return(EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_DEVIO */
|
49
kernel/system/do_endksig.c
Normal file
49
kernel/system/do_endksig.c
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/* The system call that is implemented in this file:
|
||||||
|
* SYS_SIGCTL # signal handling functionality
|
||||||
|
*
|
||||||
|
* The parameters and types for this system call are:
|
||||||
|
* SIG_REQUEST # request to perform (long)
|
||||||
|
* SIG_PROC # process to signal/ pending (int)
|
||||||
|
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||||
|
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||||
|
* SIG_MAP # bit map with pending signals (long)
|
||||||
|
* SIG_NUMBER # signal number to send to process (int)
|
||||||
|
*
|
||||||
|
* Supported request types are in the parameter SIG_REQUEST:
|
||||||
|
* S_GETSIG # get a pending kernel signal
|
||||||
|
* S_ENDSIG # signal has been processed
|
||||||
|
* S_SENDSIG # deliver a POSIX-style signal
|
||||||
|
* S_SIGRETURN # return from a POSIX-style signal
|
||||||
|
* S_KILL # send a signal to a process
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/sigcontext.h>
|
||||||
|
|
||||||
|
#if USE_ENDKSIG
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_endksig *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_endksig(m_ptr)
|
||||||
|
message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Finish up after a kernel type signal, caused by a SYS_KILL message or a
|
||||||
|
* call to cause_sig by a task. This is called by the PM after processing a
|
||||||
|
* signal it got with SYS_GETKSIG.
|
||||||
|
*/
|
||||||
|
register struct proc *rp;
|
||||||
|
|
||||||
|
rp = proc_addr(m_ptr->SIG_PROC);
|
||||||
|
if (isemptyp(rp)) return(EINVAL); /* process already dead? */
|
||||||
|
|
||||||
|
/* PM has finished one kernel signal. Perhaps process is ready now? */
|
||||||
|
if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */
|
||||||
|
if ((rp->p_rts_flags &= ~SIG_PENDING)==0) /* remove pending flag */
|
||||||
|
lock_ready(rp); /* ready if no flags */
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_ENDKSIG */
|
||||||
|
|
63
kernel/system/do_exec.c
Normal file
63
kernel/system/do_exec.c
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_EXEC
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m1_i1: PR_PROC_NR (process that did exec call)
|
||||||
|
* m1_i3: PR_TRACING (flag to indicate tracing is on/ off)
|
||||||
|
* m1_p1: PR_STACK_PTR (new stack pointer)
|
||||||
|
* m1_p2: PR_NAME_PTR (pointer to program name)
|
||||||
|
* m1_p3: PR_IP_PTR (new instruction pointer)
|
||||||
|
*/
|
||||||
|
#include "../system.h"
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#if USE_EXEC
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_exec *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_exec(m_ptr)
|
||||||
|
register message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */
|
||||||
|
|
||||||
|
register struct proc *rp;
|
||||||
|
reg_t sp; /* new sp */
|
||||||
|
phys_bytes phys_name;
|
||||||
|
char *np;
|
||||||
|
|
||||||
|
rp = proc_addr(m_ptr->PR_PROC_NR);
|
||||||
|
if (m_ptr->PR_TRACING) cause_sig(m_ptr->PR_PROC_NR, SIGTRAP);
|
||||||
|
sp = (reg_t) m_ptr->PR_STACK_PTR;
|
||||||
|
rp->p_reg.sp = sp; /* set the stack pointer */
|
||||||
|
#if (CHIP == M68000)
|
||||||
|
rp->p_splow = sp; /* set the stack pointer low water */
|
||||||
|
#ifdef FPP
|
||||||
|
/* Initialize fpp for this process */
|
||||||
|
fpp_new_state(rp);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if (CHIP == INTEL) /* wipe extra LDT entries */
|
||||||
|
kmemset(&rp->p_ldt[EXTRA_LDT_INDEX], 0,
|
||||||
|
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
|
||||||
|
#endif
|
||||||
|
rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */
|
||||||
|
rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */
|
||||||
|
if (rp->p_rts_flags == 0) lock_ready(rp);
|
||||||
|
|
||||||
|
/* Save command name for debugging, ps(1) output, etc. */
|
||||||
|
phys_name = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->PR_NAME_PTR,
|
||||||
|
(vir_bytes) P_NAME_LEN - 1);
|
||||||
|
if (phys_name != 0) {
|
||||||
|
phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1);
|
||||||
|
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
|
||||||
|
*np = 0; /* mark end */
|
||||||
|
} else {
|
||||||
|
kstrncpy(rp->p_name, "<unset>", P_NAME_LEN);
|
||||||
|
}
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
#endif /* USE_EXEC */
|
||||||
|
|
||||||
|
|
||||||
|
|
42
kernel/system/do_exit.c
Normal file
42
kernel/system/do_exit.c
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_EXIT
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m1_i1: PR_PROC_NR (slot number of exiting process)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
|
||||||
|
#if USE_EXIT
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_exit *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_exit(m_ptr)
|
||||||
|
message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Handle sys_exit. A user process has exited or a system process requests
|
||||||
|
* to exit. Only the PM can request other process slots to be cleared.
|
||||||
|
* The routine to clean up a process table slot cancels outstanding timers,
|
||||||
|
* possibly removes the process from the message queues, and resets certain
|
||||||
|
* process table fields to the default values.
|
||||||
|
*/
|
||||||
|
int exit_proc_nr;
|
||||||
|
|
||||||
|
/* Determine what process exited. User processes are handled here. */
|
||||||
|
if (PM_PROC_NR == m_ptr->m_source) {
|
||||||
|
exit_proc_nr = m_ptr->PR_PROC_NR; /* get exiting process */
|
||||||
|
if (exit_proc_nr != SELF) { /* PM tries to exit self */
|
||||||
|
if (! isokprocn(exit_proc_nr)) return(EINVAL);
|
||||||
|
clear_proc(exit_proc_nr); /* exit a user process */
|
||||||
|
return(OK); /* report back to PM */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The PM or some other system process requested to be exited. */
|
||||||
|
clear_proc(m_ptr->m_source);
|
||||||
|
return(EDONTREPLY);
|
||||||
|
}
|
||||||
|
#endif /* USE_EXIT */
|
||||||
|
|
||||||
|
|
62
kernel/system/do_fork.c
Normal file
62
kernel/system/do_fork.c
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_FORK
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m1_i1: PR_PROC_NR (child's process table slot)
|
||||||
|
* m1_i2: PR_PPROC_NR (parent, process that forked)
|
||||||
|
* m1_i3: PR_PID (child pid received from PM)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <signal.h>
|
||||||
|
#if (CHIP == INTEL)
|
||||||
|
#include "../protect.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_FORK
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_fork *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_fork(m_ptr)
|
||||||
|
register message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Handle sys_fork(). PR_PPROC_NR has forked. The child is PR_PROC_NR. */
|
||||||
|
|
||||||
|
#if (CHIP == INTEL)
|
||||||
|
reg_t old_ldt_sel;
|
||||||
|
#endif
|
||||||
|
register struct proc *rpc;
|
||||||
|
struct proc *rpp;
|
||||||
|
|
||||||
|
rpp = proc_addr(m_ptr->PR_PPROC_NR);
|
||||||
|
rpc = proc_addr(m_ptr->PR_PROC_NR);
|
||||||
|
if (! isemptyp(rpc)) return(EINVAL);
|
||||||
|
|
||||||
|
/* Copy parent 'proc' struct to child. */
|
||||||
|
#if (CHIP == INTEL)
|
||||||
|
old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*rpc = *rpp; /* copy 'proc' struct */
|
||||||
|
|
||||||
|
#if (CHIP == INTEL)
|
||||||
|
rpc->p_ldt_sel = old_ldt_sel;
|
||||||
|
#endif
|
||||||
|
rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */
|
||||||
|
rpc->p_ntf_q = NULL; /* remove pending notifications */
|
||||||
|
|
||||||
|
/* Only one in group should have SIGNALED, child doesn't inherit tracing. */
|
||||||
|
rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */
|
||||||
|
rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP);
|
||||||
|
sigemptyset(&rpc->p_pending);
|
||||||
|
|
||||||
|
rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
|
||||||
|
rpc->p_user_time = 0; /* set all the accounting times to 0 */
|
||||||
|
rpc->p_sys_time = 0;
|
||||||
|
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_FORK */
|
||||||
|
|
|
@ -1,61 +1,3 @@
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../system.h"
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <minix/config.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_unused *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_unused(m)
|
|
||||||
message *m; /* pointer to request message */
|
|
||||||
{
|
|
||||||
kprintf("SYS task got illegal request from %d.", m->m_source);
|
|
||||||
return(EBADREQUEST); /* illegal message type */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_ABORT
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m1_i1: ABRT_HOW (how to abort, possibly fetch monitor params)
|
|
||||||
* m1_i2: ABRT_MON_PROC (proc nr to get monitor params from)
|
|
||||||
* m1_i3: ABRT_MON_LEN (length of monitor params)
|
|
||||||
* m1_p1: ABRT_MON_ADDR (virtual address of params)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_abort *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_abort(m_ptr)
|
|
||||||
message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Handle sys_abort. MINIX is unable to continue. This can originate in the
|
|
||||||
* PM (normal abort or panic) or FS (panic), or TTY (a CTRL-ALT-DEL or ESC
|
|
||||||
* after debugging dumps).
|
|
||||||
*/
|
|
||||||
int how = m_ptr->ABRT_HOW;
|
|
||||||
|
|
||||||
if (how == RBT_MONITOR) {
|
|
||||||
/* The monitor is to run the specified instructions. */
|
|
||||||
int proc_nr = m_ptr->ABRT_MON_PROC;
|
|
||||||
int length = m_ptr->ABRT_MON_LEN + 1;
|
|
||||||
vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR;
|
|
||||||
phys_bytes src_phys = numap_local(proc_nr, src_vir, length);
|
|
||||||
|
|
||||||
/* Validate length and address of shutdown code before copying. */
|
|
||||||
if (length > kinfo.params_size || src_phys == 0)
|
|
||||||
phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
|
|
||||||
else
|
|
||||||
phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
|
|
||||||
}
|
|
||||||
prepare_shutdown(how);
|
|
||||||
return(OK); /* pro-forma (really EDISASTER) */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
/* The system call implemented in this file:
|
||||||
* m_type: SYS_GETINFO
|
* m_type: SYS_GETINFO
|
||||||
*
|
*
|
||||||
|
@ -71,6 +13,10 @@ message *m_ptr; /* pointer to request message */
|
||||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
|
||||||
|
#if USE_GETINFO
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_getinfo *
|
* do_getinfo *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -96,7 +42,7 @@ register message *m_ptr; /* pointer to request message */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GET_IMAGE: {
|
case GET_IMAGE: {
|
||||||
length = sizeof(struct system_image) * IMAGE_SIZE;
|
length = sizeof(struct system_image) * NR_BOOT_PROCS;
|
||||||
src_phys = vir2phys(image);
|
src_phys = vir2phys(image);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -123,6 +69,11 @@ register message *m_ptr; /* pointer to request message */
|
||||||
src_phys = vir2phys(proc);
|
src_phys = vir2phys(proc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GET_PRIVTAB: {
|
||||||
|
length = sizeof(struct priv) * (NR_SYS_PROCS);
|
||||||
|
src_phys = vir2phys(priv);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GET_PROC: {
|
case GET_PROC: {
|
||||||
nr = (m_ptr->I_KEY_LEN == SELF) ? m_ptr->m_source : m_ptr->I_KEY_LEN;
|
nr = (m_ptr->I_KEY_LEN == SELF) ? m_ptr->m_source : m_ptr->I_KEY_LEN;
|
||||||
if (! isokprocn(nr)) return(EINVAL); /* validate request */
|
if (! isokprocn(nr)) return(EINVAL); /* validate request */
|
||||||
|
@ -147,7 +98,7 @@ register message *m_ptr; /* pointer to request message */
|
||||||
src_phys = vir2phys(&kmess);
|
src_phys = vir2phys(&kmess);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if ENABLE_LOCK_TIMING
|
#if DEBUG_TIME_LOCKS
|
||||||
case GET_LOCKTIMING: {
|
case GET_LOCKTIMING: {
|
||||||
length = sizeof(timingdata);
|
length = sizeof(timingdata);
|
||||||
src_phys = vir2phys(timingdata);
|
src_phys = vir2phys(timingdata);
|
||||||
|
@ -167,4 +118,5 @@ register message *m_ptr; /* pointer to request message */
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* USE_GETINFO */
|
||||||
|
|
55
kernel/system/do_getksig.c
Normal file
55
kernel/system/do_getksig.c
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/* The system call that is implemented in this file:
|
||||||
|
* SYS_SIGCTL # signal handling functionality
|
||||||
|
*
|
||||||
|
* The parameters and types for this system call are:
|
||||||
|
* SIG_REQUEST # request to perform (long)
|
||||||
|
* SIG_PROC # process to signal/ pending (int)
|
||||||
|
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||||
|
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||||
|
* SIG_MAP # bit map with pending signals (long)
|
||||||
|
* SIG_NUMBER # signal number to send to process (int)
|
||||||
|
*
|
||||||
|
* Supported request types are in the parameter SIG_REQUEST:
|
||||||
|
* S_GETSIG # get a pending kernel signal
|
||||||
|
* S_ENDSIG # signal has been processed
|
||||||
|
* S_SENDSIG # deliver a POSIX-style signal
|
||||||
|
* S_SIGRETURN # return from a POSIX-style signal
|
||||||
|
* S_KILL # send a signal to a process
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/sigcontext.h>
|
||||||
|
|
||||||
|
#if USE_GETKSIG
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_getksig *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_getksig(m_ptr)
|
||||||
|
message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* PM is ready to accept signals and repeatedly does a system call to get
|
||||||
|
* one. Find a process with pending signals. If no signals are available,
|
||||||
|
* return NONE in the process number field.
|
||||||
|
*/
|
||||||
|
register struct proc *rp;
|
||||||
|
|
||||||
|
/* Find the next process with pending signals. */
|
||||||
|
for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
|
||||||
|
if (rp->p_rts_flags & SIGNALED) {
|
||||||
|
m_ptr->SIG_PROC = rp->p_nr;
|
||||||
|
m_ptr->SIG_MAP = rp->p_pending;
|
||||||
|
sigemptyset(&rp->p_pending); /* ball is in PM's court */
|
||||||
|
rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No process with pending signals was found. */
|
||||||
|
m_ptr->SIG_PROC = NONE;
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
#endif /* USE_GETKSIG */
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../system.h"
|
#include "../system.h"
|
||||||
|
|
||||||
|
#if USE_IRQCTL
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* do_irqctl *
|
* do_irqctl *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -95,3 +96,5 @@ register message *m_ptr; /* pointer to request message */
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* USE_IRQCTL */
|
||||||
|
|
41
kernel/system/do_kill.c
Normal file
41
kernel/system/do_kill.c
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* The system call that is implemented in this file:
|
||||||
|
* SYS_SIGCTL # signal handling functionality
|
||||||
|
*
|
||||||
|
* The parameters and types for this system call are:
|
||||||
|
* SIG_REQUEST # request to perform (long)
|
||||||
|
* SIG_PROC # process to signal/ pending (int)
|
||||||
|
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||||
|
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||||
|
* SIG_MAP # bit map with pending signals (long)
|
||||||
|
* SIG_NUMBER # signal number to send to process (int)
|
||||||
|
*
|
||||||
|
* Supported request types are in the parameter SIG_REQUEST:
|
||||||
|
* S_GETSIG # get a pending kernel signal
|
||||||
|
* S_ENDSIG # signal has been processed
|
||||||
|
* S_SENDSIG # deliver a POSIX-style signal
|
||||||
|
* S_SIGRETURN # return from a POSIX-style signal
|
||||||
|
* S_KILL # send a signal to a process
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/sigcontext.h>
|
||||||
|
|
||||||
|
#if USE_KILL
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_kill *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_kill(m_ptr)
|
||||||
|
message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Handle sys_kill(). Cause a signal to be sent to a process via PM.
|
||||||
|
* Note that this has nothing to do with the kill (2) system call, this
|
||||||
|
* is how the FS (and possibly other servers) get access to cause_sig.
|
||||||
|
*/
|
||||||
|
cause_sig(m_ptr->SIG_PROC, m_ptr->SIG_NUMBER);
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_KILL */
|
||||||
|
|
27
kernel/system/do_memset.c
Normal file
27
kernel/system/do_memset.c
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_MEMSET
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m5_l1: CP_SRC_ADDR (virtual address)
|
||||||
|
* m5_l2: CP_DST_ADDR (returns physical address)
|
||||||
|
* m5_l3: CP_NR_BYTES (size of datastructure)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
|
||||||
|
#if USE_MEMSET
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_memset *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_memset(m_ptr)
|
||||||
|
register message *m_ptr;
|
||||||
|
{
|
||||||
|
/* Handle sys_memset(). */
|
||||||
|
phys_zero((phys_bytes) m_ptr->MEM_PTR, (phys_bytes) m_ptr->MEM_COUNT);
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_MEMSET */
|
||||||
|
|
||||||
|
|
53
kernel/system/do_newmap.c
Normal file
53
kernel/system/do_newmap.c
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_NEWMAP
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m1_i1: PR_PROC_NR (install new map for this process)
|
||||||
|
* m1_p1: PR_MEM_PTR (pointer to memory map)
|
||||||
|
*/
|
||||||
|
#include "../system.h"
|
||||||
|
|
||||||
|
#if USE_NEWMAP
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_newmap *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_newmap(m_ptr)
|
||||||
|
message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Handle sys_newmap(). Fetch the memory map from PM. */
|
||||||
|
|
||||||
|
register struct proc *rp;
|
||||||
|
phys_bytes src_phys;
|
||||||
|
int caller; /* whose space has the new map (usually PM) */
|
||||||
|
int k; /* process whose map is to be loaded */
|
||||||
|
int old_flags; /* value of flags before modification */
|
||||||
|
struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
|
||||||
|
|
||||||
|
/* Extract message parameters and copy new memory map from PM. */
|
||||||
|
caller = m_ptr->m_source;
|
||||||
|
k = m_ptr->PR_PROC_NR;
|
||||||
|
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
|
||||||
|
if (!isokprocn(k)) return(EINVAL);
|
||||||
|
rp = proc_addr(k); /* ptr to entry of user getting new map */
|
||||||
|
|
||||||
|
/* Copy the map from PM. */
|
||||||
|
src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr,
|
||||||
|
sizeof(rp->p_memmap));
|
||||||
|
if (src_phys == 0) return(EFAULT);
|
||||||
|
phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap));
|
||||||
|
|
||||||
|
#if (CHIP != M68000)
|
||||||
|
alloc_segments(rp);
|
||||||
|
#else
|
||||||
|
pmmu_init_proc(rp);
|
||||||
|
#endif
|
||||||
|
old_flags = rp->p_rts_flags; /* save the previous value of the flags */
|
||||||
|
rp->p_rts_flags &= ~NO_MAP;
|
||||||
|
if (old_flags != 0 && rp->p_rts_flags == 0) lock_ready(rp);
|
||||||
|
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
#endif /* USE_NEWMAP */
|
||||||
|
|
||||||
|
|
50
kernel/system/do_schedctl.c
Normal file
50
kernel/system/do_schedctl.c
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_SCHEDCTL
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m1_i1: PR_PROC_NR process number to change priority
|
||||||
|
* m1_i2: PR_PRIORITY the new priority
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <minix/type.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
#if USE_SCHEDCTL
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_schedctl *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_schedctl(message *m_ptr)
|
||||||
|
{
|
||||||
|
int proc_nr, pri, new_q ;
|
||||||
|
register struct proc *rp;
|
||||||
|
|
||||||
|
/* Extract the message parameters and do sanity checking. */
|
||||||
|
proc_nr = m_ptr->PR_PROC_NR;
|
||||||
|
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||||
|
pri = m_ptr->PR_PRIORITY;
|
||||||
|
if (pri < PRIO_MIN || pri > PRIO_MAX) return(EINVAL);
|
||||||
|
|
||||||
|
/* The priority is currently between PRIO_MIN and PRIO_MAX. We have to
|
||||||
|
* scale this between MIN_USER_Q and MAX_USER_Q.
|
||||||
|
*/
|
||||||
|
new_q = MAX_USER_Q + (pri-PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) /
|
||||||
|
(PRIO_MAX-PRIO_MIN+1);
|
||||||
|
if (new_q < MAX_USER_Q) new_q = MAX_USER_Q; /* shouldn't happen */
|
||||||
|
if (new_q > MIN_USER_Q) new_q = MIN_USER_Q; /* shouldn't happen */
|
||||||
|
|
||||||
|
/* Make sure the process is not running while changing its priority; the
|
||||||
|
* max_priority is the base priority. Put the process back in its new
|
||||||
|
* queue if it is runnable.
|
||||||
|
*/
|
||||||
|
rp = proc_addr(proc_nr);
|
||||||
|
lock_unready(rp);
|
||||||
|
rp->p_max_priority = rp->p_priority = new_q;
|
||||||
|
if (! rp->p_rts_flags) lock_ready(rp);
|
||||||
|
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_SCHEDCTL */
|
||||||
|
|
61
kernel/system/do_sdevio.c
Normal file
61
kernel/system/do_sdevio.c
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_SDEVIO
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m2_i3: DIO_REQUEST (request input or output)
|
||||||
|
* m2_i1: DIO_TYPE (flag indicating byte, word, or long)
|
||||||
|
* m2_l1: DIO_PORT (port to read/ write)
|
||||||
|
* m2_p1: DIO_VEC_ADDR (virtual address of buffer)
|
||||||
|
* m2_l2: DIO_VEC_SIZE (number of elements)
|
||||||
|
* m2_i2: DIO_VEC_PROC (process where buffer is)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <minix/devio.h>
|
||||||
|
|
||||||
|
#if USE_SDEVIO
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_sdevio *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_sdevio(m_ptr)
|
||||||
|
register message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
int proc_nr = m_ptr->DIO_VEC_PROC;
|
||||||
|
int count = m_ptr->DIO_VEC_SIZE;
|
||||||
|
long port = m_ptr->DIO_PORT;
|
||||||
|
phys_bytes phys_buf;
|
||||||
|
|
||||||
|
/* Check if process number is OK. */
|
||||||
|
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||||
|
if (! isokprocn(proc_nr))
|
||||||
|
return(EINVAL);
|
||||||
|
|
||||||
|
/* Get and check physical address. */
|
||||||
|
if ((phys_buf = numap_local(proc_nr, (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
|
||||||
|
return(EFAULT);
|
||||||
|
|
||||||
|
/* Perform device I/O for bytes and words. Longs are not supported. */
|
||||||
|
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
|
||||||
|
switch (m_ptr->DIO_TYPE) {
|
||||||
|
case DIO_BYTE: phys_insb(port, phys_buf, count); break;
|
||||||
|
case DIO_WORD: phys_insw(port, phys_buf, count); break;
|
||||||
|
default: return(EINVAL);
|
||||||
|
}
|
||||||
|
} else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) {
|
||||||
|
switch (m_ptr->DIO_TYPE) {
|
||||||
|
case DIO_BYTE: phys_outsb(port, phys_buf, count); break;
|
||||||
|
case DIO_WORD: phys_outsw(port, phys_buf, count); break;
|
||||||
|
default: return(EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return(EINVAL);
|
||||||
|
}
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_SDEVIO */
|
||||||
|
|
||||||
|
|
||||||
|
|
84
kernel/system/do_segctl.c
Normal file
84
kernel/system/do_segctl.c
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_SEGCTL
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m4_l3: SEG_PHYS (physical base address)
|
||||||
|
* m4_l4: SEG_SIZE (size of segment)
|
||||||
|
* m4_l1: SEG_SELECT (return segment selector here)
|
||||||
|
* m4_l2: SEG_OFFSET (return offset within segment here)
|
||||||
|
* m4_l5: SEG_INDEX (return index into remote memory map here)
|
||||||
|
*
|
||||||
|
* Author:
|
||||||
|
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||||
|
*/
|
||||||
|
#include "../system.h"
|
||||||
|
#include "../protect.h"
|
||||||
|
|
||||||
|
#if USE_SEGCTL
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_segctl *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_segctl(m_ptr)
|
||||||
|
register message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Return a segment selector and offset that can be used to reach a physical
|
||||||
|
* address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
|
||||||
|
*/
|
||||||
|
u16_t selector;
|
||||||
|
vir_bytes offset;
|
||||||
|
int i, index;
|
||||||
|
register struct proc *rp;
|
||||||
|
phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS;
|
||||||
|
vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* First check if there is a slot available for this segment. */
|
||||||
|
rp = proc_addr(m_ptr->m_source);
|
||||||
|
index = -1;
|
||||||
|
for (i=0; i < NR_REMOTE_SEGS; i++) {
|
||||||
|
if (! rp->p_priv->s_farmem[i].in_use) {
|
||||||
|
index = i;
|
||||||
|
rp->p_priv->s_farmem[i].in_use = TRUE;
|
||||||
|
rp->p_priv->s_farmem[i].mem_phys = phys;
|
||||||
|
rp->p_priv->s_farmem[i].mem_len = size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index < 0) return(ENOSPC);
|
||||||
|
|
||||||
|
|
||||||
|
if (! machine.protected) {
|
||||||
|
selector = phys / HCLICK_SIZE;
|
||||||
|
offset = phys % HCLICK_SIZE;
|
||||||
|
result = OK;
|
||||||
|
} else {
|
||||||
|
/* Check if the segment size can be recorded in bytes, that is, check
|
||||||
|
* if descriptor's limit field can delimited the allowed memory region
|
||||||
|
* precisely. This works up to 1MB. If the size is larger, 4K pages
|
||||||
|
* instead of bytes are used.
|
||||||
|
*/
|
||||||
|
if (size < BYTE_GRAN_MAX) {
|
||||||
|
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size,
|
||||||
|
USER_PRIVILEGE);
|
||||||
|
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
|
||||||
|
offset = 0;
|
||||||
|
result = OK;
|
||||||
|
} else {
|
||||||
|
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0,
|
||||||
|
USER_PRIVILEGE);
|
||||||
|
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
|
||||||
|
offset = phys & 0xFFFF;
|
||||||
|
result = OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request successfully done. Now return the result. */
|
||||||
|
m_ptr->SEG_INDEX = index | REMOTE_SEG;
|
||||||
|
m_ptr->SEG_SELECT = selector;
|
||||||
|
m_ptr->SEG_OFFSET = offset;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_SEGCTL */
|
||||||
|
|
79
kernel/system/do_sigreturn.c
Normal file
79
kernel/system/do_sigreturn.c
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/* The system call that is implemented in this file:
|
||||||
|
* SYS_SIGCTL # signal handling functionality
|
||||||
|
*
|
||||||
|
* The parameters and types for this system call are:
|
||||||
|
* SIG_REQUEST # request to perform (long)
|
||||||
|
* SIG_PROC # process to signal/ pending (int)
|
||||||
|
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||||
|
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||||
|
* SIG_MAP # bit map with pending signals (long)
|
||||||
|
* SIG_NUMBER # signal number to send to process (int)
|
||||||
|
*
|
||||||
|
* Supported request types are in the parameter SIG_REQUEST:
|
||||||
|
* S_GETSIG # get a pending kernel signal
|
||||||
|
* S_ENDSIG # signal has been processed
|
||||||
|
* S_SENDSIG # deliver a POSIX-style signal
|
||||||
|
* S_SIGRETURN # return from a POSIX-style signal
|
||||||
|
* S_KILL # send a signal to a process
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/sigcontext.h>
|
||||||
|
|
||||||
|
#if USE_SIGRETURN
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_sigreturn *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_sigreturn(m_ptr)
|
||||||
|
message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* POSIX style signals require sys_sigreturn to put things in order before
|
||||||
|
* the signalled process can resume execution
|
||||||
|
*/
|
||||||
|
struct sigcontext sc;
|
||||||
|
register struct proc *rp;
|
||||||
|
phys_bytes src_phys;
|
||||||
|
|
||||||
|
rp = proc_addr(m_ptr->SIG_PROC);
|
||||||
|
|
||||||
|
/* Copy in the sigcontext structure. */
|
||||||
|
src_phys = umap_local(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
|
||||||
|
(vir_bytes) sizeof(struct sigcontext));
|
||||||
|
if (src_phys == 0) return(EFAULT);
|
||||||
|
phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
|
||||||
|
|
||||||
|
/* Make sure that this is not just a jump buffer. */
|
||||||
|
if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
|
||||||
|
|
||||||
|
/* Fix up only certain key registers if the compiler doesn't use
|
||||||
|
* register variables within functions containing setjmp.
|
||||||
|
*/
|
||||||
|
if (sc.sc_flags & SC_NOREGLOCALS) {
|
||||||
|
rp->p_reg.retreg = sc.sc_retreg;
|
||||||
|
rp->p_reg.fp = sc.sc_fp;
|
||||||
|
rp->p_reg.pc = sc.sc_pc;
|
||||||
|
rp->p_reg.sp = sc.sc_sp;
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
sc.sc_psw = rp->p_reg.psw;
|
||||||
|
|
||||||
|
#if (CHIP == INTEL)
|
||||||
|
/* Don't panic kernel if user gave bad selectors. */
|
||||||
|
sc.sc_cs = rp->p_reg.cs;
|
||||||
|
sc.sc_ds = rp->p_reg.ds;
|
||||||
|
sc.sc_es = rp->p_reg.es;
|
||||||
|
#if _WORD_SIZE == 4
|
||||||
|
sc.sc_fs = rp->p_reg.fs;
|
||||||
|
sc.sc_gs = rp->p_reg.gs;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Restore the registers. */
|
||||||
|
kmemcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
#endif /* USE_SIGRETURN */
|
||||||
|
|
||||||
|
|
89
kernel/system/do_sigsend.c
Normal file
89
kernel/system/do_sigsend.c
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/* The system call that is implemented in this file:
|
||||||
|
* SYS_SIGCTL # signal handling functionality
|
||||||
|
*
|
||||||
|
* The parameters and types for this system call are:
|
||||||
|
* SIG_REQUEST # request to perform (long)
|
||||||
|
* SIG_PROC # process to signal/ pending (int)
|
||||||
|
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
||||||
|
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
||||||
|
* SIG_MAP # bit map with pending signals (long)
|
||||||
|
* SIG_NUMBER # signal number to send to process (int)
|
||||||
|
*
|
||||||
|
* Supported request types are in the parameter SIG_REQUEST:
|
||||||
|
* S_GETSIG # get a pending kernel signal
|
||||||
|
* S_ENDSIG # signal has been processed
|
||||||
|
* S_SENDSIG # deliver a POSIX-style signal
|
||||||
|
* S_SIGRETURN # return from a POSIX-style signal
|
||||||
|
* S_KILL # send a signal to a process
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/sigcontext.h>
|
||||||
|
|
||||||
|
#if USE_SIGSEND
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_sigsend *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_sigsend(m_ptr)
|
||||||
|
message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Handle sys_sigsend, POSIX-style signal handling. */
|
||||||
|
|
||||||
|
struct sigmsg smsg;
|
||||||
|
register struct proc *rp;
|
||||||
|
phys_bytes src_phys, dst_phys;
|
||||||
|
struct sigcontext sc, *scp;
|
||||||
|
struct sigframe fr, *frp;
|
||||||
|
|
||||||
|
rp = proc_addr(m_ptr->SIG_PROC);
|
||||||
|
|
||||||
|
/* Get the sigmsg structure into our address space. */
|
||||||
|
src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes)
|
||||||
|
m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg));
|
||||||
|
if (src_phys == 0) return(EFAULT);
|
||||||
|
phys_copy(src_phys,vir2phys(&smsg),(phys_bytes) sizeof(struct sigmsg));
|
||||||
|
|
||||||
|
/* Compute the user stack pointer where sigcontext will be stored. */
|
||||||
|
scp = (struct sigcontext *) smsg.sm_stkptr - 1;
|
||||||
|
|
||||||
|
/* Copy the registers to the sigcontext structure. */
|
||||||
|
kmemcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
|
||||||
|
|
||||||
|
/* Finish the sigcontext initialization. */
|
||||||
|
sc.sc_flags = SC_SIGCONTEXT;
|
||||||
|
sc.sc_mask = smsg.sm_mask;
|
||||||
|
|
||||||
|
/* Copy the sigcontext structure to the user's stack. */
|
||||||
|
dst_phys = umap_local(rp, D, (vir_bytes) scp,
|
||||||
|
(vir_bytes) sizeof(struct sigcontext));
|
||||||
|
if (dst_phys == 0) return(EFAULT);
|
||||||
|
phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
|
||||||
|
|
||||||
|
/* Initialize the sigframe structure. */
|
||||||
|
frp = (struct sigframe *) scp - 1;
|
||||||
|
fr.sf_scpcopy = scp;
|
||||||
|
fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
|
||||||
|
fr.sf_fp = rp->p_reg.fp;
|
||||||
|
rp->p_reg.fp = (reg_t) &frp->sf_fp;
|
||||||
|
fr.sf_scp = scp;
|
||||||
|
fr.sf_code = 0; /* XXX - should be used for type of FP exception */
|
||||||
|
fr.sf_signo = smsg.sm_signo;
|
||||||
|
fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
|
||||||
|
|
||||||
|
/* Copy the sigframe structure to the user's stack. */
|
||||||
|
dst_phys = umap_local(rp, D, (vir_bytes) frp,
|
||||||
|
(vir_bytes) sizeof(struct sigframe));
|
||||||
|
if (dst_phys == 0) return(EFAULT);
|
||||||
|
phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
|
||||||
|
|
||||||
|
/* Reset user registers to execute the signal handler. */
|
||||||
|
rp->p_reg.sp = (reg_t) frp;
|
||||||
|
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
|
||||||
|
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_SIGSEND */
|
||||||
|
|
72
kernel/system/do_svrctl.c
Normal file
72
kernel/system/do_svrctl.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_SVRCTL
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m2_i1: CTL_PROC_NR (process number of caller)
|
||||||
|
* m2_i2: CTL_REQUEST (request type)
|
||||||
|
* m2_i3: CTL_MM_PRIV (privilege)
|
||||||
|
* m2_l1: CTL_SEND_MASK (new send mask to be installed)
|
||||||
|
* m2_l2: CTL_PROC_TYPE (new process type)
|
||||||
|
* m2_p1: CTL_ARG_PTR (argument pointer)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include "../ipc.h"
|
||||||
|
#include <sys/svrctl.h>
|
||||||
|
|
||||||
|
#if USE_SVRCTL
|
||||||
|
|
||||||
|
/* NOTE: this call will radically change! */
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_svrctl *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_svrctl(m_ptr)
|
||||||
|
message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
register struct proc *rp;
|
||||||
|
register struct priv *sp;
|
||||||
|
int proc_nr, rights;
|
||||||
|
int request;
|
||||||
|
vir_bytes argp;
|
||||||
|
|
||||||
|
/* Extract message parameters. */
|
||||||
|
proc_nr = m_ptr->CTL_PROC_NR;
|
||||||
|
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||||
|
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||||
|
|
||||||
|
request = m_ptr->CTL_REQUEST;
|
||||||
|
rights = m_ptr->CTL_MM_PRIV;
|
||||||
|
argp = (vir_bytes) m_ptr->CTL_ARG_PTR;
|
||||||
|
rp = proc_addr(proc_nr);
|
||||||
|
|
||||||
|
/* Check if the PM privileges are super user. */
|
||||||
|
if (!rights || !isuserp(rp))
|
||||||
|
return(EPERM);
|
||||||
|
|
||||||
|
/* See what is requested and handle the request. */
|
||||||
|
switch (request) {
|
||||||
|
case SYSSIGNON: {
|
||||||
|
/* Make this process a server. The system processes should be able
|
||||||
|
* to communicate with this new server, so update their send masks
|
||||||
|
* as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Find a new system privileges structure for this process. */
|
||||||
|
for (sp=BEG_PRIV_ADDR; sp< END_PRIV_ADDR; sp++)
|
||||||
|
if (sp->s_proc_nr == NONE) break;
|
||||||
|
if (sp->s_proc_nr != NONE) return(ENOSPC);
|
||||||
|
|
||||||
|
/* Now update the process' privileges as requested. */
|
||||||
|
rp->p_priv = sp; /* assign to process */
|
||||||
|
rp->p_priv->s_proc_nr = proc_nr(rp); /* set association */
|
||||||
|
rp->p_priv->s_call_mask = SYSTEM_CALL_MASK;
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return(EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_SVRCTL */
|
||||||
|
|
40
kernel/system/do_times.c
Normal file
40
kernel/system/do_times.c
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_TIMES
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m4_l1: T_PROC_NR (get info for this process)
|
||||||
|
* m4_l1: T_USER_TIME (return values ...)
|
||||||
|
* m4_l2: T_SYSTEM_TIME
|
||||||
|
* m4_l5: T_BOOT_TICKS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
|
||||||
|
#if USE_TIMES
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_times *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_times(m_ptr)
|
||||||
|
register message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Handle sys_times(). Retrieve the accounting information. */
|
||||||
|
register struct proc *rp;
|
||||||
|
int proc_nr;
|
||||||
|
|
||||||
|
/* Insert the times needed by the SYS_TIMES system call in the message.
|
||||||
|
* The clock's interrupt handler may run to update the user or system time
|
||||||
|
* while in this code, but that cannot do any harm.
|
||||||
|
*/
|
||||||
|
proc_nr = (m_ptr->T_PROC_NR == SELF) ? m_ptr->m_source : m_ptr->T_PROC_NR;
|
||||||
|
if (isokprocn(proc_nr)) {
|
||||||
|
rp = proc_addr(m_ptr->T_PROC_NR);
|
||||||
|
m_ptr->T_USER_TIME = rp->p_user_time;
|
||||||
|
m_ptr->T_SYSTEM_TIME = rp->p_sys_time;
|
||||||
|
}
|
||||||
|
m_ptr->T_BOOT_TICKS = get_uptime();
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_TIMES */
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
* m2_l2: CTL_DATA data to be written or returned here
|
* m2_l2: CTL_DATA data to be written or returned here
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../system.h"
|
#include "../system.h"
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
|
||||||
|
#if USE_TRACE
|
||||||
|
|
||||||
/*==========================================================================*
|
/*==========================================================================*
|
||||||
* do_trace *
|
* do_trace *
|
||||||
|
@ -138,3 +138,4 @@ register message *m_ptr;
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* USE_TRACE */
|
52
kernel/system/do_umap.c
Normal file
52
kernel/system/do_umap.c
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_UMAP
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m5_i1: CP_SRC_PROC_NR (process number)
|
||||||
|
* m5_c1: CP_SRC_SPACE (segment where address is: T, D, or S)
|
||||||
|
* m5_l1: CP_SRC_ADDR (virtual address)
|
||||||
|
* m5_l2: CP_DST_ADDR (returns physical address)
|
||||||
|
* m5_l3: CP_NR_BYTES (size of datastructure)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
|
||||||
|
#if USE_UMAP
|
||||||
|
|
||||||
|
/*==========================================================================*
|
||||||
|
* do_umap *
|
||||||
|
*==========================================================================*/
|
||||||
|
PUBLIC int do_umap(m_ptr)
|
||||||
|
register message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Map virtual address to physical, for non-kernel processes. */
|
||||||
|
int seg_type = m_ptr->CP_SRC_SPACE & SEGMENT_TYPE;
|
||||||
|
int seg_index = m_ptr->CP_SRC_SPACE & SEGMENT_INDEX;
|
||||||
|
vir_bytes offset = m_ptr->CP_SRC_ADDR;
|
||||||
|
int count = m_ptr->CP_NR_BYTES;
|
||||||
|
int proc_nr = (int) m_ptr->CP_SRC_PROC_NR;
|
||||||
|
phys_bytes phys_addr;
|
||||||
|
|
||||||
|
/* Verify process number. */
|
||||||
|
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
||||||
|
if (! isokprocn(proc_nr)) return(EINVAL);
|
||||||
|
|
||||||
|
/* See which mapping should be made. */
|
||||||
|
switch(seg_type) {
|
||||||
|
case LOCAL_SEG:
|
||||||
|
phys_addr = umap_local(proc_addr(proc_nr), seg_index, offset, count);
|
||||||
|
break;
|
||||||
|
case REMOTE_SEG:
|
||||||
|
phys_addr = umap_remote(proc_addr(proc_nr), seg_index, offset, count);
|
||||||
|
break;
|
||||||
|
case BIOS_SEG:
|
||||||
|
phys_addr = umap_bios(proc_addr(proc_nr), offset, count);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return(EINVAL);
|
||||||
|
}
|
||||||
|
m_ptr->CP_DST_ADDR = phys_addr;
|
||||||
|
return (phys_addr == 0) ? EFAULT: OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* USE_UMAP */
|
15
kernel/system/do_unused.c
Normal file
15
kernel/system/do_unused.c
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_unused *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_unused(m)
|
||||||
|
message *m; /* pointer to request message */
|
||||||
|
{
|
||||||
|
kprintf("SYSTEM got unused request %d", m->m_type);
|
||||||
|
kprintf("from %d.\n", m->m_source);
|
||||||
|
return(EBADREQUEST); /* illegal message type */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
67
kernel/system/do_vcopy.c
Normal file
67
kernel/system/do_vcopy.c
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/* The system call implemented in this file:
|
||||||
|
* m_type: SYS_VIRVCOPY, SYS_PHYSVCOPY
|
||||||
|
*
|
||||||
|
* The parameters for this system call are:
|
||||||
|
* m5_c1: CP_SRC_SPACE
|
||||||
|
* m5_l1: CP_SRC_ADDR
|
||||||
|
* m5_i1: CP_SRC_PROC_NR
|
||||||
|
* m5_c2: CP_DST_SPACE
|
||||||
|
* m5_l2: CP_DST_ADDR
|
||||||
|
* m5_i2: CP_DST_PROC_NR
|
||||||
|
* m5_l3: CP_NR_BYTES
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <minix/type.h>
|
||||||
|
|
||||||
|
#if (USE_VIRVCOPY || USE_PHYSVCOPY)
|
||||||
|
|
||||||
|
/* Buffer to hold copy request vector from user. */
|
||||||
|
PRIVATE struct vir_cp_req vir_cp_req[VCOPY_VEC_SIZE];
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_vcopy *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_vcopy(m_ptr)
|
||||||
|
register message *m_ptr; /* pointer to request message */
|
||||||
|
{
|
||||||
|
/* Handle sys_virvcopy(). Handle virtual copy requests from vector. */
|
||||||
|
int nr_req;
|
||||||
|
int caller_pid;
|
||||||
|
vir_bytes caller_vir;
|
||||||
|
phys_bytes caller_phys;
|
||||||
|
phys_bytes kernel_phys;
|
||||||
|
phys_bytes bytes;
|
||||||
|
int i,s;
|
||||||
|
struct vir_cp_req *req;
|
||||||
|
|
||||||
|
/* Check if request vector size is ok. */
|
||||||
|
nr_req = (unsigned) m_ptr->VCP_VEC_SIZE;
|
||||||
|
if (nr_req > VCOPY_VEC_SIZE) return(EINVAL);
|
||||||
|
bytes = nr_req * sizeof(struct vir_cp_req);
|
||||||
|
|
||||||
|
/* Calculate physical addresses and copy (port,value)-pairs from user. */
|
||||||
|
caller_pid = (int) m_ptr->m_source;
|
||||||
|
caller_vir = (vir_bytes) m_ptr->VCP_VEC_ADDR;
|
||||||
|
caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes);
|
||||||
|
if (0 == caller_phys) return(EFAULT);
|
||||||
|
kernel_phys = vir2phys(vir_cp_req);
|
||||||
|
phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
|
||||||
|
|
||||||
|
/* Assume vector with requests is correct. Try to copy everything. */
|
||||||
|
for (i=0; i<nr_req; i++) {
|
||||||
|
|
||||||
|
req = &vir_cp_req[i];
|
||||||
|
|
||||||
|
/* Check if physical addressing is used without SYS_PHYSVCOPY. */
|
||||||
|
if (((req->src.segment | req->dst.segment) & PHYS_SEG) &&
|
||||||
|
m_ptr->m_type != SYS_PHYSVCOPY)
|
||||||
|
return(EPERM);
|
||||||
|
if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK)
|
||||||
|
return(s);
|
||||||
|
}
|
||||||
|
return(OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* (USE_VIRVCOPY || USE_PHYSVCOPY) */
|
||||||
|
|
|
@ -1,100 +1,3 @@
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_DEVIO
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m2_i3: DIO_REQUEST (request input or output)
|
|
||||||
* m2_i1: DIO_TYPE (flag indicating byte, word, or long)
|
|
||||||
* m2_l1: DIO_PORT (port to read/ write)
|
|
||||||
* m2_l2: DIO_VALUE (value to write/ return value read)
|
|
||||||
*
|
|
||||||
* Author:
|
|
||||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../system.h"
|
|
||||||
#include "../debug.h"
|
|
||||||
#include <minix/devio.h>
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_devio *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_devio(m_ptr)
|
|
||||||
register message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* perform actual device I/O for byte, word, and long values */
|
|
||||||
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
|
|
||||||
switch (m_ptr->DIO_TYPE) {
|
|
||||||
case DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break;
|
|
||||||
case DIO_WORD: m_ptr->DIO_VALUE = inw(m_ptr->DIO_PORT); break;
|
|
||||||
case DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break;
|
|
||||||
default: return(EINVAL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (m_ptr->DIO_TYPE) {
|
|
||||||
case DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
|
||||||
case DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
|
||||||
case DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
|
|
||||||
default: return(EINVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_SDEVIO
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m2_i3: DIO_REQUEST (request input or output)
|
|
||||||
* m2_i1: DIO_TYPE (flag indicating byte, word, or long)
|
|
||||||
* m2_l1: DIO_PORT (port to read/ write)
|
|
||||||
* m2_p1: DIO_VEC_ADDR (virtual address of buffer)
|
|
||||||
* m2_l2: DIO_VEC_SIZE (number of elements)
|
|
||||||
* m2_i2: DIO_VEC_PROC (process where buffer is)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_sdevio *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_sdevio(m_ptr)
|
|
||||||
register message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
int proc_nr = m_ptr->DIO_VEC_PROC;
|
|
||||||
int count = m_ptr->DIO_VEC_SIZE;
|
|
||||||
long port = m_ptr->DIO_PORT;
|
|
||||||
phys_bytes phys_buf;
|
|
||||||
|
|
||||||
/* Check if process number is OK. */
|
|
||||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
|
||||||
if (! isokprocn(proc_nr))
|
|
||||||
return(EINVAL);
|
|
||||||
|
|
||||||
/* Get and check physical address. */
|
|
||||||
if ((phys_buf = numap_local(proc_nr, (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
|
|
||||||
return(EFAULT);
|
|
||||||
|
|
||||||
/* Perform device I/O for bytes and words. Longs are not supported. */
|
|
||||||
if (m_ptr->DIO_REQUEST == DIO_INPUT) {
|
|
||||||
switch (m_ptr->DIO_TYPE) {
|
|
||||||
case DIO_BYTE: phys_insb(port, phys_buf, count); break;
|
|
||||||
case DIO_WORD: phys_insw(port, phys_buf, count); break;
|
|
||||||
default: return(EINVAL);
|
|
||||||
}
|
|
||||||
} else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) {
|
|
||||||
switch (m_ptr->DIO_TYPE) {
|
|
||||||
case DIO_BYTE: phys_outsb(port, phys_buf, count); break;
|
|
||||||
case DIO_WORD: phys_outsw(port, phys_buf, count); break;
|
|
||||||
default: return(EINVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return(EINVAL);
|
|
||||||
}
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
/* The system call implemented in this file:
|
||||||
* m_type: SYS_VDEVIO
|
* m_type: SYS_VDEVIO
|
||||||
*
|
*
|
||||||
|
@ -105,6 +8,12 @@ register message *m_ptr; /* pointer to request message */
|
||||||
* m2_i2: DIO_VEC_SIZE (number of ports to read or write)
|
* m2_i2: DIO_VEC_SIZE (number of ports to read or write)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "../system.h"
|
||||||
|
#include <minix/devio.h>
|
||||||
|
|
||||||
|
#if USE_VDEVIO
|
||||||
|
|
||||||
|
|
||||||
/* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
|
/* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
|
||||||
PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE];
|
PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE];
|
||||||
|
|
||||||
|
@ -213,4 +122,5 @@ register message *m_ptr; /* pointer to request message */
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* USE_VDEVIO */
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_SETPRIORITY
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m1_i1: which
|
|
||||||
* m1_i2: who
|
|
||||||
* m1_i3: prio
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../system.h"
|
|
||||||
#include <minix/type.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_setpriority *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_setpriority(message *m_ptr)
|
|
||||||
{
|
|
||||||
int which_proc, pri, q, niceperq;
|
|
||||||
struct proc *which_procp;
|
|
||||||
|
|
||||||
which_proc = m_ptr->m1_i1;
|
|
||||||
pri = m_ptr->m1_i2;
|
|
||||||
|
|
||||||
/* pri is currently between PRIO_MIN and PRIO_MAX. We have to
|
|
||||||
* scale this between MIN_USER_Q and MAX_USER_Q.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(pri < PRIO_MIN || pri > PRIO_MAX)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
if(which_proc < 0 || which_proc >= NR_TASKS+NR_PROCS)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
which_procp = proc_addr(which_proc);
|
|
||||||
|
|
||||||
q = MAX_USER_Q + (pri - PRIO_MIN) * (MIN_USER_Q-MAX_USER_Q+1) / (PRIO_MAX-PRIO_MIN+1);
|
|
||||||
|
|
||||||
/* The below shouldn't happen. */
|
|
||||||
if(q < MAX_USER_Q) q = MAX_USER_Q;
|
|
||||||
if(q > MIN_USER_Q) q = MIN_USER_Q;
|
|
||||||
|
|
||||||
/* max_priority is the base priority. */
|
|
||||||
which_procp->p_max_priority = q;
|
|
||||||
lock_unready(which_procp);
|
|
||||||
which_procp->p_priority = q;
|
|
||||||
|
|
||||||
/* Runnable? Put it (back) on its new run queue. */
|
|
||||||
if(!which_procp->p_rts_flags)
|
|
||||||
lock_ready(which_procp);
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,209 +0,0 @@
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_FORK
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m1_i1: PR_PROC_NR (child's process table slot)
|
|
||||||
* m1_i2: PR_PPROC_NR (parent, process that forked)
|
|
||||||
* m1_i3: PR_PID (child pid received from PM)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../system.h"
|
|
||||||
#include "../sendmask.h"
|
|
||||||
#include <signal.h>
|
|
||||||
#if (CHIP == INTEL)
|
|
||||||
#include "../protect.h"
|
|
||||||
#endif
|
|
||||||
#include "../debug.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_fork *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_fork(m_ptr)
|
|
||||||
register message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Handle sys_fork(). PR_PPROC_NR has forked. The child is PR_PROC_NR. */
|
|
||||||
|
|
||||||
#if (CHIP == INTEL)
|
|
||||||
reg_t old_ldt_sel;
|
|
||||||
#endif
|
|
||||||
register struct proc *rpc;
|
|
||||||
struct proc *rpp;
|
|
||||||
|
|
||||||
rpp = proc_addr(m_ptr->PR_PPROC_NR);
|
|
||||||
rpc = proc_addr(m_ptr->PR_PROC_NR);
|
|
||||||
if (! isemptyp(rpc)) return(EINVAL);
|
|
||||||
|
|
||||||
/* Copy parent 'proc' struct to child. */
|
|
||||||
#if (CHIP == INTEL)
|
|
||||||
old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*rpc = *rpp; /* copy 'proc' struct */
|
|
||||||
|
|
||||||
#if (CHIP == INTEL)
|
|
||||||
rpc->p_ldt_sel = old_ldt_sel;
|
|
||||||
#endif
|
|
||||||
rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */
|
|
||||||
rpc->p_ntf_q = NULL; /* remove pending notifications */
|
|
||||||
|
|
||||||
/* Only one in group should have SIGNALED, child doesn't inherit tracing. */
|
|
||||||
rpc->p_rts_flags |= NO_MAP; /* inhibit process from running */
|
|
||||||
rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP);
|
|
||||||
sigemptyset(&rpc->p_pending);
|
|
||||||
|
|
||||||
rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
|
|
||||||
rpc->p_user_time = 0; /* set all the accounting times to 0 */
|
|
||||||
rpc->p_sys_time = 0;
|
|
||||||
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_NEWMAP
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m1_i1: PR_PROC_NR (install new map for this process)
|
|
||||||
* m1_p1: PR_MEM_PTR (pointer to memory map)
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_newmap *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_newmap(m_ptr)
|
|
||||||
message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Handle sys_newmap(). Fetch the memory map from PM. */
|
|
||||||
|
|
||||||
register struct proc *rp;
|
|
||||||
phys_bytes src_phys;
|
|
||||||
int caller; /* whose space has the new map (usually PM) */
|
|
||||||
int k; /* process whose map is to be loaded */
|
|
||||||
int old_flags; /* value of flags before modification */
|
|
||||||
struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
|
|
||||||
|
|
||||||
/* Extract message parameters and copy new memory map from PM. */
|
|
||||||
caller = m_ptr->m_source;
|
|
||||||
k = m_ptr->PR_PROC_NR;
|
|
||||||
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
|
|
||||||
if (!isokprocn(k)) return(EINVAL);
|
|
||||||
rp = proc_addr(k); /* ptr to entry of user getting new map */
|
|
||||||
|
|
||||||
/* Copy the map from PM. */
|
|
||||||
src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr,
|
|
||||||
sizeof(rp->p_memmap));
|
|
||||||
if (src_phys == 0) return(EFAULT);
|
|
||||||
phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap));
|
|
||||||
|
|
||||||
#if (CHIP != M68000)
|
|
||||||
alloc_segments(rp);
|
|
||||||
#else
|
|
||||||
pmmu_init_proc(rp);
|
|
||||||
#endif
|
|
||||||
old_flags = rp->p_rts_flags; /* save the previous value of the flags */
|
|
||||||
rp->p_rts_flags &= ~NO_MAP;
|
|
||||||
if (old_flags != 0 && rp->p_rts_flags == 0) lock_ready(rp);
|
|
||||||
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_EXEC
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m1_i1: PR_PROC_NR (process that did exec call)
|
|
||||||
* m1_i3: PR_TRACING (flag to indicate tracing is on/ off)
|
|
||||||
* m1_p1: PR_STACK_PTR (new stack pointer)
|
|
||||||
* m1_p2: PR_NAME_PTR (pointer to program name)
|
|
||||||
* m1_p3: PR_IP_PTR (new instruction pointer)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_exec *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_exec(m_ptr)
|
|
||||||
register message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */
|
|
||||||
|
|
||||||
register struct proc *rp;
|
|
||||||
reg_t sp; /* new sp */
|
|
||||||
phys_bytes phys_name;
|
|
||||||
char *np;
|
|
||||||
|
|
||||||
rp = proc_addr(m_ptr->PR_PROC_NR);
|
|
||||||
if (m_ptr->PR_TRACING) cause_sig(m_ptr->PR_PROC_NR, SIGTRAP);
|
|
||||||
sp = (reg_t) m_ptr->PR_STACK_PTR;
|
|
||||||
rp->p_reg.sp = sp; /* set the stack pointer */
|
|
||||||
#if (CHIP == M68000)
|
|
||||||
rp->p_splow = sp; /* set the stack pointer low water */
|
|
||||||
#ifdef FPP
|
|
||||||
/* Initialize fpp for this process */
|
|
||||||
fpp_new_state(rp);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#if (CHIP == INTEL) /* wipe extra LDT entries */
|
|
||||||
kmemset(&rp->p_ldt[EXTRA_LDT_INDEX], 0,
|
|
||||||
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
|
|
||||||
#endif
|
|
||||||
rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */
|
|
||||||
rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */
|
|
||||||
if (rp->p_rts_flags == 0) lock_ready(rp);
|
|
||||||
|
|
||||||
/* Save command name for debugging, ps(1) output, etc. */
|
|
||||||
phys_name = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->PR_NAME_PTR,
|
|
||||||
(vir_bytes) P_NAME_LEN - 1);
|
|
||||||
if (phys_name != 0) {
|
|
||||||
phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1);
|
|
||||||
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
|
|
||||||
*np = 0; /* mark end */
|
|
||||||
} else {
|
|
||||||
kstrncpy(rp->p_name, "<unset>", P_NAME_LEN);
|
|
||||||
}
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_XIT
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m1_i1: PR_PROC_NR (slot number of exiting process)
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_xit *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_xit(m_ptr)
|
|
||||||
message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Handle sys_exit. A user process has exited or a system process requests
|
|
||||||
* to exit. Only the PM can request other process slots to be cleared.
|
|
||||||
* The routine to clean up a process table slot cancels outstanding timers,
|
|
||||||
* possibly removes the process from the message queues, and resets certain
|
|
||||||
* process table fields to the default values.
|
|
||||||
*/
|
|
||||||
int exit_proc_nr;
|
|
||||||
|
|
||||||
/* Determine what process exited. */
|
|
||||||
if (PM_PROC_NR == m_ptr->m_source) {
|
|
||||||
exit_proc_nr = m_ptr->PR_PROC_NR; /* get exiting process */
|
|
||||||
if (exit_proc_nr != SELF) { /* PM tries to exit self */
|
|
||||||
if (! isokprocn(exit_proc_nr)) return(EINVAL);
|
|
||||||
clear_proc(exit_proc_nr); /* exit a user process */
|
|
||||||
return(OK); /* report back to PM */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The PM or some other system process requested to be exited. */
|
|
||||||
clear_proc(m_ptr->m_source);
|
|
||||||
return(EDONTREPLY);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,192 +0,0 @@
|
||||||
/* The system call that is implemented in this file:
|
|
||||||
* SYS_SIGCTL # signal handling functionality
|
|
||||||
*
|
|
||||||
* The parameters and types for this system call are:
|
|
||||||
* SIG_REQUEST # request to perform (long)
|
|
||||||
* SIG_PROC # process to signal/ pending (int)
|
|
||||||
* SIG_CTXT_PTR # pointer to sigcontext structure (pointer)
|
|
||||||
* SIG_FLAGS # flags for S_SIGRETURN call (int)
|
|
||||||
* SIG_MAP # bit map with pending signals (long)
|
|
||||||
* SIG_NUMBER # signal number to send to process (int)
|
|
||||||
*
|
|
||||||
* Supported request types are in the parameter SIG_REQUEST:
|
|
||||||
* S_GETSIG # get a pending kernel signal
|
|
||||||
* S_ENDSIG # signal has been processed
|
|
||||||
* S_SENDSIG # deliver a POSIX-style signal
|
|
||||||
* S_SIGRETURN # return from a POSIX-style signal
|
|
||||||
* S_KILL # send a signal to a process
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../system.h"
|
|
||||||
#include <signal.h>
|
|
||||||
#include <sys/sigcontext.h>
|
|
||||||
|
|
||||||
/* PM is ready to accept signals and repeatedly does a system call to get
|
|
||||||
* one. Find a process with pending signals. If no signals are available,
|
|
||||||
* return NONE in the process number field.
|
|
||||||
*/
|
|
||||||
PUBLIC int do_getsig(m_ptr)
|
|
||||||
message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
register struct proc *rp;
|
|
||||||
|
|
||||||
/* Find the next process with pending signals. */
|
|
||||||
for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
|
|
||||||
if (rp->p_rts_flags & SIGNALED) {
|
|
||||||
m_ptr->SIG_PROC = rp->p_nr;
|
|
||||||
m_ptr->SIG_MAP = rp->p_pending;
|
|
||||||
sigemptyset(&rp->p_pending); /* ball is in PM's court */
|
|
||||||
rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No process with pending signals was found. */
|
|
||||||
m_ptr->SIG_PROC = NONE;
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
PUBLIC int do_endsig(m_ptr)
|
|
||||||
message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Finish up after a kernel type signal, caused by a SYS_KILL message or a
|
|
||||||
* call to cause_sig by a task. This is called by the PM after processing a
|
|
||||||
* signal it got with SYS_GETSIG.
|
|
||||||
*/
|
|
||||||
register struct proc *rp;
|
|
||||||
|
|
||||||
rp = proc_addr(m_ptr->SIG_PROC);
|
|
||||||
if (isemptyp(rp)) return(EINVAL); /* process already dead? */
|
|
||||||
|
|
||||||
/* PM has finished one kernel signal. Perhaps process is ready now? */
|
|
||||||
if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */
|
|
||||||
if ((rp->p_rts_flags &= ~SIG_PENDING)==0) /* remove pending flag */
|
|
||||||
lock_ready(rp); /* ready if no flags */
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
PUBLIC int do_sigsend(m_ptr)
|
|
||||||
message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Handle sys_sigsend, POSIX-style signal handling. */
|
|
||||||
|
|
||||||
struct sigmsg smsg;
|
|
||||||
register struct proc *rp;
|
|
||||||
phys_bytes src_phys, dst_phys;
|
|
||||||
struct sigcontext sc, *scp;
|
|
||||||
struct sigframe fr, *frp;
|
|
||||||
|
|
||||||
rp = proc_addr(m_ptr->SIG_PROC);
|
|
||||||
|
|
||||||
/* Get the sigmsg structure into our address space. */
|
|
||||||
src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes)
|
|
||||||
m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg));
|
|
||||||
if (src_phys == 0) return(EFAULT);
|
|
||||||
phys_copy(src_phys,vir2phys(&smsg),(phys_bytes) sizeof(struct sigmsg));
|
|
||||||
|
|
||||||
/* Compute the user stack pointer where sigcontext will be stored. */
|
|
||||||
scp = (struct sigcontext *) smsg.sm_stkptr - 1;
|
|
||||||
|
|
||||||
/* Copy the registers to the sigcontext structure. */
|
|
||||||
kmemcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
|
|
||||||
|
|
||||||
/* Finish the sigcontext initialization. */
|
|
||||||
sc.sc_flags = SC_SIGCONTEXT;
|
|
||||||
sc.sc_mask = smsg.sm_mask;
|
|
||||||
|
|
||||||
/* Copy the sigcontext structure to the user's stack. */
|
|
||||||
dst_phys = umap_local(rp, D, (vir_bytes) scp,
|
|
||||||
(vir_bytes) sizeof(struct sigcontext));
|
|
||||||
if (dst_phys == 0) return(EFAULT);
|
|
||||||
phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
|
|
||||||
|
|
||||||
/* Initialize the sigframe structure. */
|
|
||||||
frp = (struct sigframe *) scp - 1;
|
|
||||||
fr.sf_scpcopy = scp;
|
|
||||||
fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
|
|
||||||
fr.sf_fp = rp->p_reg.fp;
|
|
||||||
rp->p_reg.fp = (reg_t) &frp->sf_fp;
|
|
||||||
fr.sf_scp = scp;
|
|
||||||
fr.sf_code = 0; /* XXX - should be used for type of FP exception */
|
|
||||||
fr.sf_signo = smsg.sm_signo;
|
|
||||||
fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
|
|
||||||
|
|
||||||
/* Copy the sigframe structure to the user's stack. */
|
|
||||||
dst_phys = umap_local(rp, D, (vir_bytes) frp,
|
|
||||||
(vir_bytes) sizeof(struct sigframe));
|
|
||||||
if (dst_phys == 0) return(EFAULT);
|
|
||||||
phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
|
|
||||||
|
|
||||||
/* Reset user registers to execute the signal handler. */
|
|
||||||
rp->p_reg.sp = (reg_t) frp;
|
|
||||||
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
|
|
||||||
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
PUBLIC int do_sigreturn(m_ptr)
|
|
||||||
message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* POSIX style signals require sys_sigreturn to put things in order before
|
|
||||||
* the signalled process can resume execution
|
|
||||||
*/
|
|
||||||
struct sigcontext sc;
|
|
||||||
register struct proc *rp;
|
|
||||||
phys_bytes src_phys;
|
|
||||||
|
|
||||||
rp = proc_addr(m_ptr->SIG_PROC);
|
|
||||||
|
|
||||||
/* Copy in the sigcontext structure. */
|
|
||||||
src_phys = umap_local(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
|
|
||||||
(vir_bytes) sizeof(struct sigcontext));
|
|
||||||
if (src_phys == 0) return(EFAULT);
|
|
||||||
phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
|
|
||||||
|
|
||||||
/* Make sure that this is not just a jmp_buf. */
|
|
||||||
if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
|
|
||||||
|
|
||||||
/* Fix up only certain key registers if the compiler doesn't use
|
|
||||||
* register variables within functions containing setjmp.
|
|
||||||
*/
|
|
||||||
if (sc.sc_flags & SC_NOREGLOCALS) {
|
|
||||||
rp->p_reg.retreg = sc.sc_retreg;
|
|
||||||
rp->p_reg.fp = sc.sc_fp;
|
|
||||||
rp->p_reg.pc = sc.sc_pc;
|
|
||||||
rp->p_reg.sp = sc.sc_sp;
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
sc.sc_psw = rp->p_reg.psw;
|
|
||||||
|
|
||||||
#if (CHIP == INTEL)
|
|
||||||
/* Don't panic kernel if user gave bad selectors. */
|
|
||||||
sc.sc_cs = rp->p_reg.cs;
|
|
||||||
sc.sc_ds = rp->p_reg.ds;
|
|
||||||
sc.sc_es = rp->p_reg.es;
|
|
||||||
#if _WORD_SIZE == 4
|
|
||||||
sc.sc_fs = rp->p_reg.fs;
|
|
||||||
sc.sc_gs = rp->p_reg.gs;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Restore the registers. */
|
|
||||||
kmemcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_sigctl *
|
|
||||||
*===========================================================================*/
|
|
||||||
|
|
||||||
PUBLIC int do_kill(m_ptr)
|
|
||||||
message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Handle sys_kill(). Cause a signal to be sent to a process via PM.
|
|
||||||
* Note that this has nothing to do with the kill (2) system call, this
|
|
||||||
* is how the FS (and possibly other servers) get access to cause_sig.
|
|
||||||
*/
|
|
||||||
cause_sig(m_ptr->SIG_PROC, m_ptr->SIG_NUMBER);
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,178 +0,0 @@
|
||||||
#include "../kernel.h"
|
|
||||||
#include "../ipc.h"
|
|
||||||
#include "../system.h"
|
|
||||||
#include "../protect.h"
|
|
||||||
#include <sys/svrctl.h>
|
|
||||||
#include "../sendmask.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_SVRCTL
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m2_i1: CTL_PROC_NR (process number of caller)
|
|
||||||
* m2_i2: CTL_REQUEST (request type)
|
|
||||||
* m2_i3: CTL_MM_PRIV (privilege)
|
|
||||||
* m2_l1: CTL_SEND_MASK (new send mask to be installed)
|
|
||||||
* m2_l2: CTL_PROC_TYPE (new process type)
|
|
||||||
* m2_p1: CTL_ARG_PTR (argument pointer)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* NOTE: this call will radically change! */
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_svrctl *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_svrctl(m_ptr)
|
|
||||||
message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
register struct proc *rp;
|
|
||||||
int proc_nr, priv;
|
|
||||||
int request;
|
|
||||||
vir_bytes argp;
|
|
||||||
|
|
||||||
/* Extract message parameters. */
|
|
||||||
proc_nr = m_ptr->CTL_PROC_NR;
|
|
||||||
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
|
|
||||||
if (! isokprocn(proc_nr)) return(EINVAL);
|
|
||||||
|
|
||||||
request = m_ptr->CTL_REQUEST;
|
|
||||||
priv = m_ptr->CTL_MM_PRIV;
|
|
||||||
argp = (vir_bytes) m_ptr->CTL_ARG_PTR;
|
|
||||||
rp = proc_addr(proc_nr);
|
|
||||||
|
|
||||||
/* Check if the PM privileges are super user. */
|
|
||||||
if (!priv || !isuserp(rp))
|
|
||||||
return(EPERM);
|
|
||||||
|
|
||||||
/* See what is requested and handle the request. */
|
|
||||||
switch (request) {
|
|
||||||
case SYSSIGNON: {
|
|
||||||
/* Make this process a server. The system processes should be able
|
|
||||||
* to communicate with this new server, so update their send masks
|
|
||||||
* as well.
|
|
||||||
*/
|
|
||||||
/* fall through */
|
|
||||||
}
|
|
||||||
case SYSSENDMASK: {
|
|
||||||
rp->p_call_mask = SYSTEM_CALL_MASK;
|
|
||||||
rp->p_sendmask = ALLOW_ALL_MASK;
|
|
||||||
send_mask_allow(proc_addr(USR8139)->p_sendmask, proc_nr);
|
|
||||||
send_mask_allow(proc_addr(PM_PROC_NR)->p_sendmask, proc_nr);
|
|
||||||
send_mask_allow(proc_addr(FS_PROC_NR)->p_sendmask, proc_nr);
|
|
||||||
send_mask_allow(proc_addr(IS_PROC_NR)->p_sendmask, proc_nr);
|
|
||||||
send_mask_allow(proc_addr(CLOCK)->p_sendmask, proc_nr);
|
|
||||||
send_mask_allow(proc_addr(SYSTASK)->p_sendmask, proc_nr);
|
|
||||||
send_mask_allow(proc_addr(FXP)->p_sendmask, proc_nr);
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return(EINVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_SEGCTL
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m4_l3: SEG_PHYS (physical base address)
|
|
||||||
* m4_l4: SEG_SIZE (size of segment)
|
|
||||||
* m4_l1: SEG_SELECT (return segment selector here)
|
|
||||||
* m4_l2: SEG_OFFSET (return offset within segment here)
|
|
||||||
* m4_l5: SEG_INDEX (return index into remote memory map here)
|
|
||||||
*
|
|
||||||
* Author:
|
|
||||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_segctl *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_segctl(m_ptr)
|
|
||||||
register message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
/* Return a segment selector and offset that can be used to reach a physical
|
|
||||||
* address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
|
|
||||||
*/
|
|
||||||
u16_t selector;
|
|
||||||
vir_bytes offset;
|
|
||||||
int i, index;
|
|
||||||
register struct proc *rp;
|
|
||||||
phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS;
|
|
||||||
vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
/* First check if there is a slot available for this segment. */
|
|
||||||
rp = proc_addr(m_ptr->m_source);
|
|
||||||
index = -1;
|
|
||||||
for (i=0; i < NR_REMOTE_SEGS; i++) {
|
|
||||||
if (! rp->p_farmem[i].in_use) {
|
|
||||||
index = i;
|
|
||||||
rp->p_farmem[i].in_use = TRUE;
|
|
||||||
rp->p_farmem[i].mem_phys = phys;
|
|
||||||
rp->p_farmem[i].mem_len = size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (index < 0) return(ENOSPC);
|
|
||||||
|
|
||||||
|
|
||||||
if (! machine.protected) {
|
|
||||||
selector = phys / HCLICK_SIZE;
|
|
||||||
offset = phys % HCLICK_SIZE;
|
|
||||||
result = OK;
|
|
||||||
} else {
|
|
||||||
/* Check if the segment size can be recorded in bytes, that is, check
|
|
||||||
* if descriptor's limit field can delimited the allowed memory region
|
|
||||||
* precisely. This works up to 1MB. If the size is larger, 4K pages
|
|
||||||
* instead of bytes are used.
|
|
||||||
*/
|
|
||||||
if (size < BYTE_GRAN_MAX) {
|
|
||||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size,
|
|
||||||
USER_PRIVILEGE);
|
|
||||||
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
|
|
||||||
offset = 0;
|
|
||||||
result = OK;
|
|
||||||
} else {
|
|
||||||
init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0,
|
|
||||||
USER_PRIVILEGE);
|
|
||||||
selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
|
|
||||||
offset = phys & 0xFFFF;
|
|
||||||
result = OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Request successfully done. Now return the result. */
|
|
||||||
m_ptr->SEG_INDEX = index | REMOTE_SEG;
|
|
||||||
m_ptr->SEG_SELECT = selector;
|
|
||||||
m_ptr->SEG_OFFSET = offset;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* The system call implemented in this file:
|
|
||||||
* m_type: SYS_IOPENABLE
|
|
||||||
*
|
|
||||||
* The parameters for this system call are:
|
|
||||||
* m2_i2: PROC_NR (process to give I/O Protection Level bits)
|
|
||||||
*
|
|
||||||
* Author:
|
|
||||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_iopenable *
|
|
||||||
*===========================================================================*/
|
|
||||||
PUBLIC int do_iopenable(m_ptr)
|
|
||||||
register message *m_ptr; /* pointer to request message */
|
|
||||||
{
|
|
||||||
#if ENABLE_USERPRIV && ENABLE_USERIOPL
|
|
||||||
enable_iop(proc_addr(m_ptr->PROC_NR));
|
|
||||||
return(OK);
|
|
||||||
#else
|
|
||||||
return(EPERM);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
#include "sendmask.h"
|
|
||||||
#include <minix/com.h>
|
#include <minix/com.h>
|
||||||
#include <ibm/int86.h>
|
#include <ibm/int86.h>
|
||||||
|
|
||||||
|
@ -61,43 +60,46 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
|
||||||
* routine and stack size is also provided.
|
* routine and stack size is also provided.
|
||||||
*/
|
*/
|
||||||
#define IDLE_F (PREEMPTIBLE | BILLABLE)
|
#define IDLE_F (PREEMPTIBLE | BILLABLE)
|
||||||
#define USER_F (PREEMPTIBLE | SCHED_Q_HEAD)
|
#define USER_F (PREEMPTIBLE | RDY_Q_HEAD)
|
||||||
#define SYS_F (PREEMPTIBLE)
|
#define SYS_F (PREEMPTIBLE | SYS_PROC)
|
||||||
|
#define TCB_F (SYS_PROC) /* trusted computing base */
|
||||||
|
|
||||||
#define IDLE_T 32 /* ticks */
|
#define IDLE_T 32 /* ticks */
|
||||||
#define USER_T 8 /* ticks */
|
#define USER_T 8 /* ticks */
|
||||||
#define SYS_T 16 /* ticks */
|
#define SYS_T 16 /* ticks */
|
||||||
|
|
||||||
PUBLIC struct system_image image[] = {
|
PUBLIC struct system_image image[] = {
|
||||||
{ IDLE, idle_task, IDLE_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_CALL_MASK, DENY_ALL_MASK, "IDLE" },
|
{ IDLE, idle_task, IDLE_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_CALL_MASK, 0, "IDLE" },
|
||||||
{ CLOCK, clock_task, 0, SYS_T, TASK_Q, CLOCK_S, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "CLOCK" },
|
{ CLOCK, clock_task, TCB_F, SYS_T, TASK_Q, CLOCK_S, SYSTEM_CALL_MASK, 0, "CLOCK" },
|
||||||
{ SYSTASK, sys_task, 0, SYS_T, TASK_Q, SYSTEM_S, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "SYS" },
|
{ SYSTEM, sys_task, TCB_F, SYS_T, TASK_Q, SYSTEM_S, SYSTEM_CALL_MASK, 0, "SYS" },
|
||||||
{ HARDWARE, 0, 0, SYS_T, TASK_Q, HARDWARE_S, EMPTY_CALL_MASK, ALLOW_ALL_MASK,"HARDW." },
|
{ HARDWARE, 0, 0, SYS_T, TASK_Q, HARDWARE_S, EMPTY_CALL_MASK, 0,"KERNEL" },
|
||||||
{ PM_PROC_NR, 0, 0, SYS_T, 3, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "PM" },
|
{ PM_PROC_NR, 0, TCB_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "PM" },
|
||||||
{ FS_PROC_NR, 0, 0, SYS_T, 3, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "FS" },
|
{ FS_PROC_NR, 0, TCB_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "FS" },
|
||||||
{ IS_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "IS" },
|
{ IS_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "IS" },
|
||||||
{ TTY, 0, SYS_F, SYS_T, 1, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "TTY" },
|
{ TTY, 0, SYS_F, SYS_T, 1, 0, SYSTEM_CALL_MASK, 0, "TTY" },
|
||||||
{ MEMORY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "MEMORY" },
|
{ MEMORY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "MEMORY" },
|
||||||
#if ENABLE_AT_WINI
|
#if ENABLE_AT_WINI
|
||||||
{ AT_WINI, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "AT_WINI" },
|
{ AT_WINI, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "AT_WINI" },
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_FLOPPY
|
#if ENABLE_FLOPPY
|
||||||
{ FLOPPY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "FLOPPY" },
|
{ FLOPPY, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "FLOPPY" },
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_PRINTER
|
#if ENABLE_PRINTER
|
||||||
{ PRINTER, 0, SYS_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "PRINTER" },
|
{ PRINTER, 0, SYS_F, SYS_T, 3, 0, SYSTEM_CALL_MASK, 0, "PRINTER" },
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_RTL8139
|
#if ENABLE_RTL8139
|
||||||
{ USR8139, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "RTL8139" },
|
{ USR8139, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "RTL8139" },
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_FXP
|
#if ENABLE_FXP
|
||||||
{ FXP, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "FXP" },
|
{ FXP, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "FXP" },
|
||||||
#endif
|
#endif
|
||||||
#if ENABLE_DPETH
|
#if ENABLE_DPETH
|
||||||
{ DPETH, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "DPETH" },
|
{ DPETH, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "DPETH" },
|
||||||
#endif
|
#endif
|
||||||
{ LOG_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, ALLOW_ALL_MASK, "LOG" },
|
#if ENABLE_LOG
|
||||||
{ INIT_PROC_NR, 0, USER_F, USER_T, USER_Q, 0, USER_CALL_MASK, USER_PROC_SENDMASK, "INIT" },
|
{ LOG_PROC_NR, 0, SYS_F, SYS_T, 2, 0, SYSTEM_CALL_MASK, 0, "LOG" },
|
||||||
|
#endif
|
||||||
|
{ INIT_PROC_NR, 0, USER_F, USER_T, USER_Q, 0, USER_CALL_MASK, 0, "INIT" },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Verify the size of the system image table at compile time. If the number
|
/* Verify the size of the system image table at compile time. If the number
|
||||||
|
@ -105,5 +107,5 @@ PUBLIC struct system_image image[] = {
|
||||||
* a compile time error. Note that no space is allocated because 'dummy' is
|
* a compile time error. Note that no space is allocated because 'dummy' is
|
||||||
* declared extern.
|
* declared extern.
|
||||||
*/
|
*/
|
||||||
extern int dummy[(IMAGE_SIZE==sizeof(image)/sizeof(struct system_image))?1:-1];
|
extern int dummy[(NR_BOOT_PROCS==sizeof(image)/sizeof(struct system_image))?1:-1];
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,12 @@ typedef _PROTOTYPE( void task_t, (void) );
|
||||||
*/
|
*/
|
||||||
typedef long karg_t; /* use largest type here */
|
typedef long karg_t; /* use largest type here */
|
||||||
|
|
||||||
/* Process related types.
|
/* Process table and system property related types. */
|
||||||
* A process number defines the index into the process table. With a signed
|
typedef int proc_nr_t; /* process table entry number */
|
||||||
* short we can support up to 256 user processes and more kernel tasks than
|
typedef short sys_id_t; /* system process index */
|
||||||
* one can ever create.
|
typedef struct { /* bitmap for system indexes */
|
||||||
*/
|
bitchunk_t chunk[BITMAP_CHUNKS(NR_SYS_PROCS)];
|
||||||
typedef short proc_nr_t; /* process table entry number */
|
} sys_map_t;
|
||||||
typedef unsigned long send_mask_t; /* bit mask for sender */
|
|
||||||
|
|
||||||
struct system_image {
|
struct system_image {
|
||||||
proc_nr_t proc_nr; /* process number to use */
|
proc_nr_t proc_nr; /* process number to use */
|
||||||
|
@ -24,7 +23,7 @@ struct system_image {
|
||||||
int priority; /* scheduling priority */
|
int priority; /* scheduling priority */
|
||||||
int stksize; /* stack size for tasks */
|
int stksize; /* stack size for tasks */
|
||||||
char call_mask; /* allowed system calls */
|
char call_mask; /* allowed system calls */
|
||||||
send_mask_t sendmask; /* send mask protection */
|
long send_mask; /* send mask protection */
|
||||||
char proc_name[P_NAME_LEN]; /* name in process table */
|
char proc_name[P_NAME_LEN]; /* name in process table */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue