summaryrefslogtreecommitdiff
path: root/minix/servers/pm/schedule.c
blob: df2cc8d2ef2c4c5320b06c0dee82d319c14d182c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "pm.h"
#include <assert.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/config.h>
#include <minix/sched.h>
#include <minix/sysinfo.h>
#include <minix/type.h>
#include <machine/archtypes.h>
#include <lib.h>
#include "mproc.h"

#include <machine/archtypes.h>
#include <minix/timers.h>
#include "kernel/proc.h"

/*===========================================================================*
 *				init_scheduling				     *
 *===========================================================================*/
void sched_init(void)
{
	struct mproc *trmp;
	endpoint_t parent_e;
	int proc_nr, s;

	for (proc_nr=0, trmp=mproc; proc_nr < NR_PROCS; proc_nr++, trmp++) {
		/* Don't take over system processes. When the system starts,
		 * init is blocked on RTS_NO_QUANTUM until PM assigns a
		 * scheduler, from which other. Given that all other user
		 * processes are forked from init and system processes are
		 * managed by RS, there should be no other process that needs
		 * to be assigned a scheduler here */
		if (trmp->mp_flags & IN_USE && !(trmp->mp_flags & PRIV_PROC)) {
			assert(_ENDPOINT_P(trmp->mp_endpoint) == INIT_PROC_NR);
			parent_e = mproc[trmp->mp_parent].mp_endpoint;
			assert(parent_e == trmp->mp_endpoint);
			s = sched_start(SCHED_PROC_NR,	/* scheduler_e */
				trmp->mp_endpoint,	/* schedulee_e */
				parent_e,		/* parent_e */
				USER_Q, 		/* maxprio */
				USER_QUANTUM, 		/* quantum */
				-1,			/* don't change cpu */
				&trmp->mp_scheduler);	/* *newsched_e */
			if (s != OK) {
				printf("PM: SCHED denied taking over scheduling of %s: %d\n",
					trmp->mp_name, s);
			}
		}
 	}
}

/*===========================================================================*
 *				sched_start_user			     *
 *===========================================================================*/
int sched_start_user(endpoint_t ep, struct mproc *rmp)
{
	unsigned maxprio;
	endpoint_t inherit_from;
	int rv;

	/* convert nice to priority */
	if ((rv = nice_to_priority(rmp->mp_nice, &maxprio)) != OK) {
		return rv;
	}

	/* scheduler must know the parent, which is not the case for a child
	 * of a system process created by a regular fork; in this case the
	 * scheduler should inherit settings from init rather than the real
	 * parent
	 */
	if (mproc[rmp->mp_parent].mp_flags & PRIV_PROC) {
		assert(mproc[rmp->mp_parent].mp_scheduler == NONE);
		inherit_from = INIT_PROC_NR;
	} else {
		inherit_from = mproc[rmp->mp_parent].mp_endpoint;
	}

	/* inherit quantum */
	return sched_inherit(ep, 			/* scheduler_e */
		rmp->mp_endpoint, 			/* schedulee_e */
		inherit_from, 				/* parent_e */
		maxprio, 				/* maxprio */
		&rmp->mp_scheduler);			/* *newsched_e */
}

/*===========================================================================*
 *				sched_nice				     *
 *===========================================================================*/
int sched_nice(struct mproc *rmp, int nice)
{
	int rv;
	message m;
	unsigned maxprio;

	/* If the kernel is the scheduler, we don't allow messing with the
	 * priority. If you want to control process priority, assign the process
	 * to a user-space scheduler */
	if (rmp->mp_scheduler == KERNEL || rmp->mp_scheduler == NONE)
		return (EINVAL);

	if ((rv = nice_to_priority(nice, &maxprio)) != OK) {
		return rv;
	}

	m.m_pm_sched_scheduling_set_nice.endpoint	= rmp->mp_endpoint;
	m.m_pm_sched_scheduling_set_nice.maxprio	= maxprio;
	if ((rv = _taskcall(rmp->mp_scheduler, SCHEDULING_SET_NICE, &m))) {
		return rv;
	}

	return (OK);
}