Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/* Project:     OSLib
2
 * Description: The OS Construction Kit
3
 * Date:                1.6.2000
4
 * Idea by:             Luca Abeni & Gerardo Lamastra
5
 *
6
 * OSLib is an SO project aimed at developing a common, easy-to-use
7
 * low-level infrastructure for developing OS kernels and Embedded
8
 * Applications; it partially derives from the HARTIK project but it
9
 * currently is independently developed.
10
 *
11
 * OSLib is distributed under GPL License, and some of its code has
12
 * been derived from the Linux kernel source; also some important
13
 * ideas come from studying the DJGPP go32 extender.
14
 *
15
 * We acknowledge the Linux Community, Free Software Foundation,
16
 * D.J. Delorie and all the other developers who believe in the
17
 * freedom of software and ideas.
18
 *
19
 * For legalese, check out the included GPL license.
20
 */
21
 
22
/*      Stupid Scheduling Demo  */
23
 
24
#include <ll/i386/cons.h>
25
#include <ll/i386/tss-ctx.h>
26
#include <ll/i386/error.h>
27
#include <ll/sys/ll/ll-instr.h>
28
#include <ll/sys/ll/ll-func.h>
29
#include <ll/sys/ll/time.h>
30
#include <ll/sys/ll/event.h>
31
#include <ll/stdlib.h>
32
 
33
#define FREE 0
34
#define IDLE 1
35
 
36
struct ctx {
37
    WORD ll;
38
    struct timespec time;
39
    DWORD cputime;
40
    DWORD toexec;
41
    int acc;
42
    DWORD slice;
43
    int state;
44
};
45
 
46
struct trkevt {
47
    int thread;
48
    DWORD time;
49
    int value;
50
};
51
 
52
struct trkevt track[10000];
53
 
54
DWORD cpu[] = { 5000, 2000, 10000, 500, 5000, 6000, 20000, 1000, 7000 };
55
DWORD p[] =
56
    { 100000, 50000, 100000, 5000, 20000, 30000, 200000, 200000, 35000 };
57
 
58
#define STACK_SIZE      100000U /* Stack size in bytes          */
59
#define USE_FPU         0x0001
60
 
61
WORD th1, thm;
62
 
63
#define T 1000
64
 
65
#if 1
66
#define TO     ll_context_to
67
#define FROM   ll_context_from
68
#else
69
#define TO     ll_context_load
70
#define FROM   ll_context_save
71
#endif
72
 
73
/* For stack allocation checking */
74
BYTE stacks[STACK_SIZE];
75
#define N 10
76
 
77
struct ctx context[N];
78
int exec;
79
 
80
 
81
 
82
void endProg(void *p)
83
{
84
    int i;
85
    DWORD last[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
86
    DWORD lasttime, lastthread;
87
 
88
    lasttime = 0;
89
    lastthread = 0;
90
    for (i = 0; i < 120; i++) {
91
        if (last[track[i].thread] != 0) {
92
            if (lastthread == 3) {
93
                message("Thread %d <-- time %lu (after %lu), Thread %lu executed for %lu --- %d\n",
94
                     track[i].thread, track[i].time,
95
                     track[i].time - last[track[i].thread], lastthread,
96
                     track[i].time - lasttime, track[i].value);
97
            }
98
        }
99
        lastthread = track[i].thread;
100
        last[track[i].thread] = track[i].time;
101
        lasttime = track[i].time;
102
    }
103
 
104
    ll_abort(110);
105
}
106
 
107
int schedule(void);
108
 
109
 
110
void endBudget(void *p)
111
{
112
    struct ctx *c = p;
113
    struct timespec time, toexec, xcuted, start;
114
    int newthread;
115
 
116
    ll_gettime(TIME_NEW, &time);
117
    NULL_TIMESPEC(&toexec);
118
    ADDNANO2TIMESPEC(c->toexec, &toexec);
119
    SUBTIMESPEC(&(c->time), &toexec, &start);
120
    SUBTIMESPEC(&time, &start, &xcuted);
121
    NULL_TIMESPEC(&toexec);
122
    ADDNANO2TIMESPEC(c->cputime * 1000, &toexec);
123
    SUBTIMESPEC(&xcuted, &toexec, &start);
124
    c->acc += TIMESPEC2NANOSEC(&start);
125
 
126
    newthread = schedule();
127
    TO(context[newthread].ll);
128
}
129
 
130
int schedule(void)
131
{
132
    static int k = 0;
133
    int toe;
134
    int done;
135
 
136
    done = 0;
137
    while (!done) {
138
        exec = (exec + 1) % N;
139
        while (context[exec].state == FREE) {
140
            exec = (exec + 1) % N;
141
        }
142
/*
143
                track[k].thread = exec;
144
                track[k].value = context[exec].acc;
145
                track[k].time = ll_gettime(TIME_NEW, &(context[exec].time));
146
                k++;
147
*/
148
        ll_gettime(TIME_NEW, &(context[exec].time));
149
        toe = (context[exec].cputime * 1000 - context[exec].acc);
150
        if (toe <= 0) {
151
            context[exec].acc -= (context[exec].cputime * 1000);
152
            k--;
153
        } else {
154
            done = 1;
155
        }
156
    }
157
    context[exec].toexec = toe;
158
    ADDNANO2TIMESPEC(toe, &(context[exec].time));
159
    event_post(context[exec].time, endBudget, &(context[exec]));
160
    return exec;
161
}
162
 
163
void thread(void *p)
164
{
165
    int i, ii;
166
    int position = 0;
167
    char mark[11];
168
    int active = 1;
169
    WORD count = 0;
170
 
171
    i = *(int *) p;
172
    while (active) {
173
/*
174
                printf_xy(10, i * 2 + 1, WHITE, "%c", mark);
175
*/
176
        count++;
177
        position = (position + 1) % 10;
178
        for (ii = 0; ii < 10; ii++) {
179
            mark[ii] = ' ';
180
        }
181
        mark[10] = 0;
182
        mark[position] = 'O';
183
        printf_xy(10, i * 2 + 1, WHITE, "%s", mark);
184
        printf_xy(25, i * 2 + 1, WHITE, "%d %u", i, count);
185
        for (ii = 0; ii < 10000; ii++);
186
 
187
        if (count == 1000)
188
            active = 0;
189
    }
190
    printf_xy(20, i * 2 + 1, WHITE, "Finished %d", i);
191
}
192
 
193
void killer(void)
194
{
195
    int th;
196
 
197
    cli();
198
    context[exec].state = FREE;
199
    th = schedule();
200
    sti();
201
    TO(context[th].ll);
202
}
203
 
204
int main(int argc, char *argv[])
205
{
206
    DWORD sp1, sp2;
207
    struct ll_initparms parms;
208
    void *mbi;
209
    DWORD t, oldt, secs;
210
    int th;
211
    int i;
212
    int pars[N];
213
    struct timespec endTime;
214
 
215
    sp1 = get_SP();
216
    cli();
217
    parms.mode = LL_ONESHOT;
218
    parms.tick = T;
219
 
220
    mbi = ll_init();
221
    event_init(&parms);
222
 
223
    if (mbi == NULL) {
224
        message("Error in LowLevel initialization code...\n");
225
        sti();
226
        l1_exit(-1);
227
    }
228
    message("LowLevel started...\n");
229
    for (i = 0; i < N - 1; i++) {
230
        pars[i] = i;
231
        context[i].ll =
232
            ll_context_create(thread, &stacks[STACK_SIZE * (i + 1) / N],
233
                              &(pars[i]), killer, 0);
234
        if (context[i].ll == 0) {
235
            error("Unable to create thread");
236
            ll_abort(100);
237
        }
238
        context[i].state = IDLE;
239
        context[i].cputime = cpu[i];
240
        context[i].toexec = cpu[i];
241
        context[i].acc = 0;
242
        context[i].slice = p[i];
243
    }
244
 
245
    context[N - 1].ll = FROM();
246
    context[N - 1].state = IDLE;
247
    context[N - 1].cputime = 200;
248
    context[N - 1].slice = 20000;
249
 
250
    message("All Threads created...\n");
251
    NULL_TIMESPEC(&endTime);
252
    endTime.tv_sec = 30;
253
 
254
    event_post(endTime, endProg, NULL);
255
    sti();
256
 
257
    cli();
258
    th = schedule();
259
    sti();
260
 
261
    TO(context[th].ll);
262
 
263
    message("Thread MAIN restartin'\n");
264
 
265
    secs = 0;
266
    oldt = 0;
267
    while (secs <= 20) {
268
        cli();
269
        t = ll_gettime(TIME_NEW, NULL);
270
        sti();
271
        if (t < oldt) {
272
            message("ARGGGGG! %lu %lu\n", t, oldt);
273
            ll_abort(99);
274
        }
275
        oldt = t;
276
        if ((t / 1000000) > secs) {
277
            secs++;
278
            printf_xy(40, 20, WHITE, "%lu     %lu    ", secs, t);
279
        }
280
    }
281
    message("\n DONE: Secs = %lu\n", secs);
282
 
283
    cli();
284
    ll_end();
285
    sp2 = get_SP();
286
    message("End reached!\n");
287
    message("Actual stack : %lx - ", sp2);
288
    message("Begin stack : %lx\n", sp1);
289
    message("Check if same : %s\n", sp1 == sp2 ? "Ok :-)" : "No :-(");
290
    return 1;
291
}