⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 2 页
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/kernel/clock.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

11000	/* This file contains the code and data for the clock task.  The clock task
11001	 * accepts six message types:
11002	 *
11003	 *   HARD_INT:    a clock interrupt has occurred
11004	 *   GET_UPTIME:  get the time since boot in ticks
11005	 *   GET_TIME:    a process wants the real time in seconds
11006	 *   SET_TIME:    a process wants to set the real time in seconds
11007	 *   SET_ALARM:   a process wants to be alerted after a specified interval
11008	 *   SET_SYN_AL:  set the sync alarm
11009	 *
11010	 *
11011	 * The input message is format m6.  The parameters are as follows:
11012	 *
11013	 *     m_type    CLOCK_PROC   FUNC    NEW_TIME
11014	 * ---------------------------------------------
11015	 * | HARD_INT   |          |         |         |
11016	 * |------------+----------+---------+---------|
11017	 * | GET_UPTIME |          |         |         |
11018	 * |------------+----------+---------+---------|
11019	 * | GET_TIME   |          |         |         |
11020	 * |------------+----------+---------+---------|
11021	 * | SET_TIME   |          |         | newtime |
11022	 * |------------+----------+---------+---------|
11023	 * | SET_ALARM  | proc_nr  |f to call|  delta  |
11024	 * |------------+----------+---------+---------|
11025	 * | SET_SYN_AL | proc_nr  |         |  delta  |
11026	 * ---------------------------------------------
11027	 * NEW_TIME, DELTA_CLICKS, and SECONDS_LEFT all refer to the same field in
11028	 * the message, depending upon the message type.
11029	 *
11030	 * Reply messages are of type OK, except in the case of a HARD_INT, to
11031	 * which no reply is generated. For the GET_* messages the time is returned
11032	 * in the NEW_TIME field, and for the SET_ALARM and SET_SYN_AL the time
11033	 * in seconds remaining until the alarm is returned is returned in the same
11034	 * field.
11035	 *
11036	 * When an alarm goes off, if the caller is a user process, a SIGALRM signal
11037	 * is sent to it.  If it is a task, a function specified by the caller will
11038	 * be invoked.  This function may, for example, send a message, but only if
11039	 * it is certain that the task will be blocked when the timer goes off. A
11040	 * synchronous alarm sends a message to the synchronous alarm task, which
11041	 * in turn can dispatch a message to another server. This is the only way
11042	 * to send an alarm to a server, since servers cannot use the function-call
11043	 * mechanism available to tasks and servers cannot receive signals.
11044	 */
11045	
11046	#include "kernel.h"
11047	#include <signal.h>
11048	#include <minix/callnr.h>
11049	#include <minix/com.h>
11050	#include "proc.h"
11051	
11052	/* Constant definitions. */
11053	#define MILLISEC         100    /* how often to call the scheduler (msec) */
11054	#define SCHED_RATE (MILLISEC*HZ/1000)   /* number of ticks per schedule */
11055	
11056	/* Clock parameters. */
11057	#define COUNTER_FREQ (2*TIMER_FREQ)     /* counter frequency using sqare wave*/
11058	#define LATCH_COUNT     0x00    /* cc00xxxx, c = channel, x = any */
11059	#define SQUARE_WAVE     0x36    /* ccaammmb, a = access, m = mode, b = BCD */
11060	                                /*   11x11, 11 = LSB then MSB, x11 = sq wave */
11061	#define TIMER_COUNT ((unsigned) (TIMER_FREQ/HZ)) /* initial value for counter*/
11062	#define TIMER_FREQ  1193182L    /* clock frequency for timer in PC and AT */
11063	
11064	#define CLOCK_ACK_BIT   0x80    /* PS/2 clock interrupt acknowledge bit */
11065	
11066	/* Clock task variables. */
11067	PRIVATE clock_t realtime;       /* real time clock */
11068	PRIVATE time_t boot_time;       /* time in seconds of system boot */
11069	PRIVATE clock_t next_alarm;     /* probable time of next alarm */
11070	PRIVATE message mc;             /* message buffer for both input and output */
11071	PRIVATE int watchdog_proc;      /* contains proc_nr at call of *watch_dog[]*/
11072	PRIVATE watchdog_t watch_dog[NR_TASKS+NR_PROCS];
11073	
11074	/* Variables used by both clock task and synchronous alarm task */
11075	PRIVATE int syn_al_alive= TRUE; /* don't wake syn_alrm_task before inited*/
11076	PRIVATE int syn_table[NR_TASKS+NR_PROCS]; /* which tasks get CLOCK_INT*/
11077	
11078	/* Variables changed by interrupt handler */
11079	PRIVATE clock_t pending_ticks;  /* ticks seen by low level only */
11080	PRIVATE int sched_ticks = SCHED_RATE;   /* counter: when 0, call scheduler */
11081	PRIVATE struct proc *prev_ptr;  /* last user process run by clock task */
11082	
11083	FORWARD _PROTOTYPE( void common_setalarm, (int proc_nr,
11084	                long delta_ticks, watchdog_t fuction) );
11085	FORWARD _PROTOTYPE( void do_clocktick, (void) );
11086	FORWARD _PROTOTYPE( void do_get_time, (void) );
11087	FORWARD _PROTOTYPE( void do_getuptime, (void) );
11088	FORWARD _PROTOTYPE( void do_set_time, (message *m_ptr) );
11089	FORWARD _PROTOTYPE( void do_setalarm, (message *m_ptr) );
11090	FORWARD _PROTOTYPE( void init_clock, (void) );
11091	FORWARD _PROTOTYPE( void cause_alarm, (void) );
11092	FORWARD _PROTOTYPE( void do_setsyn_alrm, (message *m_ptr) );
11093	FORWARD _PROTOTYPE( int clock_handler, (int irq) );
11094	
11095	/*===========================================================================*
11096	 *                              clock_task                                   *
11097	 *===========================================================================*/
11098	PUBLIC void clock_task()
11099	{
11100	/* Main program of clock task.  It corrects realtime by adding pending
11101	 * ticks seen only by the interrupt service, then it determines which
11102	 * of the 6 possible calls this is by looking at 'mc.m_type'.  Then
11103	 * it dispatches.
11104	 */
11105	
11106	  int opcode;
11107	
11108	  init_clock();                 /* initialize clock task */
11109	
11110	  /* Main loop of the clock task.  Get work, process it, sometimes reply. */
11111	  while (TRUE) {
11112	     receive(ANY, &mc);         /* go get a message */
11113	     opcode = mc.m_type;        /* extract the function code */
11114	
11115	     lock();
11116	     realtime += pending_ticks; /* transfer ticks from low level handler */
11117	     pending_ticks = 0;         /* so we don't have to worry about them */
11118	     unlock();
11119	
11120	     switch (opcode) {
11121	        case HARD_INT:   do_clocktick();        break;
11122	        case GET_UPTIME: do_getuptime();        break;
11123	        case GET_TIME:   do_get_time();         break;
11124	        case SET_TIME:   do_set_time(&mc);      break;
11125	        case SET_ALARM:  do_setalarm(&mc);      break;
11126	        case SET_SYNC_AL:do_setsyn_alrm(&mc);   break;
11127	        default: panic("clock task got bad message", mc.m_type);
11128	     }
11129	
11130	    /* Send reply, except for clock tick. */
11131	    mc.m_type = OK;
11132	    if (opcode != HARD_INT) send(mc.m_source, &mc);
11133	  }
11134	}
	
	
11137	/*===========================================================================*
11138	 *                              do_clocktick                                 *
11139	 *===========================================================================*/
11140	PRIVATE void do_clocktick()
11141	{
11142	/* Despite its name, this routine is not called on every clock tick. It
11143	 * is called on those clock ticks when a lot of work needs to be done.
11144	 */
11145	
11146	  register struct proc *rp;
11147	  register int proc_nr;
11148	
11149	  if (next_alarm <= realtime) {
11150	        /* An alarm may have gone off, but proc may have exited, so check. */
11151	        next_alarm = LONG_MAX;  /* start computing next alarm */
11152	        for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
11153	                if (rp->p_alarm != 0) {
11154	                        /* See if this alarm time has been reached. */
11155	                        if (rp->p_alarm <= realtime) {
11156	                                /* A timer has gone off.  If it is a user proc,
11157	                                 * send it a signal.  If it is a task, call the
11158	                                 * function previously specified by the task.
11159	                                 */
11160	                                proc_nr = proc_number(rp);
11161	                                if (watch_dog[proc_nr+NR_TASKS]) {
11162	                                        watchdog_proc= proc_nr;
11163	                                        (*watch_dog[proc_nr+NR_TASKS])();
11164	                                }
11165	                                else
11166	                                        cause_sig(proc_nr, SIGALRM);
11167	                                rp->p_alarm = 0;
11168	                        }
11169	
11170	                        /* Work on determining which alarm is next. */
11171	                        if (rp->p_alarm != 0 && rp->p_alarm < next_alarm)
11172	                                next_alarm = rp->p_alarm;
11173	                }
11174	        }
11175	  }
11176	
11177	  /* If a user process has been running too long, pick another one. */
11178	  if (--sched_ticks == 0) {
11179	        if (bill_ptr == prev_ptr) lock_sched(); /* process has run too long */
11180	        sched_ticks = SCHED_RATE;               /* reset quantum */
11181	        prev_ptr = bill_ptr;                    /* new previous process */
11182	  }
11183	}
	
	
11186	/*===========================================================================*
11187	 *                              do_getuptime                                 *
11188	 *===========================================================================*/
11189	PRIVATE void do_getuptime()
11190	{
11191	/* Get and return the current clock uptime in ticks. */
11192	
11193	  mc.NEW_TIME = realtime;       /* current uptime */
11194	}
	
	
11197	/*===========================================================================*
11198	 *                              get_uptime                                   *
11199	 *===========================================================================*/
11200	PUBLIC clock_t get_uptime()
11201	{
11202	/* Get and return the current clock uptime in ticks.  This function is
11203	 * designed to be called from other tasks, so they can get uptime without
11204	 * the overhead of messages. It has to be careful about pending_ticks.
11205	 */
11206	
11207	  clock_t uptime;
11208	
11209	  lock();
11210	  uptime = realtime + pending_ticks;
11211	  unlock();
11212	  return(uptime);
11213	}
	
	
11216	/*===========================================================================*
11217	 *                              do_get_time                                  *
11218	 *===========================================================================*/
11219	PRIVATE void do_get_time()
11220	{
11221	/* Get and return the current clock time in seconds. */
11222	
11223	  mc.NEW_TIME = boot_time + realtime/HZ;        /* current real time */
11224	}
	
	
11227	/*===========================================================================*
11228	 *                              do_set_time                                  *
11229	 *===========================================================================*/
11230	PRIVATE void do_set_time(m_ptr)
11231	message *m_ptr;                 /* pointer to request message */
11232	{
11233	/* Set the real time clock.  Only the superuser can use this call. */
11234	
11235	  boot_time = m_ptr->NEW_TIME - realtime/HZ;
11236	}
	
	
11239	/*===========================================================================*
11240	 *                              do_setalarm                                  *
11241	 *===========================================================================*/
11242	PRIVATE void do_setalarm(m_ptr)
11243	message *m_ptr;                 /* pointer to request message */
11244	{
11245	/* A process wants an alarm signal or a task wants a given watch_dog function
11246	 * called after a specified interval.
11247	 */
11248	
11249	  register struct proc *rp;
11250	  int proc_nr;                  /* which process wants the alarm */
11251	  long delta_ticks;             /* in how many clock ticks does he want it? */
11252	  watchdog_t function;          /* function to call (tasks only) */
11253	
11254	  /* Extract the parameters from the message. */
11255	  proc_nr = m_ptr->CLOCK_PROC_NR;       /* process to interrupt later */
11256	  delta_ticks = m_ptr->DELTA_TICKS;     /* how many ticks to wait */
11257	  function = (watchdog_t) m_ptr->FUNC_TO_CALL;
11258	                                        /* function to call (tasks only) */
11259	  rp = proc_addr(proc_nr);
11260	  mc.SECONDS_LEFT = (rp->p_alarm == 0 ? 0 : (rp->p_alarm - realtime)/HZ );
11261	  if (!istaskp(rp)) function= 0;        /* user processes get signaled */
11262	  common_setalarm(proc_nr, delta_ticks, function);
11263	}
	
	
11266	/*===========================================================================*
11267	 *                              do_setsyn_alrm                               *
11268	 *===========================================================================*/
11269	PRIVATE void do_setsyn_alrm(m_ptr)
11270	message *m_ptr;                 /* pointer to request message */
11271	{
11272	/* A process wants a synchronous alarm.
11273	 */
11274	
11275	  register struct proc *rp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -