| Index: embios/trunk/thread.c | 
| — | — | @@ -31,6 +31,7 @@ | 
| 32 | 32 | struct scheduler_thread scheduler_threads[MAX_THREADS] IBSS_ATTR; | 
| 33 | 33 | struct scheduler_thread* current_thread IBSS_ATTR; | 
| 34 | 34 | uint32_t last_tick IBSS_ATTR; | 
|  | 35 | +bool scheduler_frozen IBSS_ATTR; | 
| 35 | 36 | extern struct wakeup dbgwakeup; | 
| 36 | 37 |  | 
| 37 | 38 |  | 
| — | — | @@ -217,6 +218,7 @@ | 
| 218 | 219 | void scheduler_init(void) | 
| 219 | 220 | { | 
| 220 | 221 | memset(scheduler_threads, 0, sizeof(scheduler_threads)); | 
|  | 222 | +    scheduler_frozen = false; | 
| 221 | 223 | last_tick = USEC_TIMER; | 
| 222 | 224 | current_thread = scheduler_threads; | 
| 223 | 225 | current_thread->state = THREAD_RUNNING; | 
| — | — | @@ -226,6 +228,11 @@ | 
| 227 | 229 | setup_tick(); | 
| 228 | 230 | } | 
| 229 | 231 |  | 
|  | 232 | +void scheduler_freeze(bool value) | 
|  | 233 | +{ | 
|  | 234 | +    scheduler_frozen = value; | 
|  | 235 | +} | 
|  | 236 | + | 
| 230 | 237 | void scheduler_switch(int thread) | 
| 231 | 238 | { | 
| 232 | 239 | int i; | 
| — | — | @@ -254,37 +261,41 @@ | 
| 255 | 262 | } | 
| 256 | 263 | } | 
| 257 | 264 |  | 
| 258 |  | -    for (i = 0; i < MAX_THREADS; i++)
 | 
| 259 |  | -        if (scheduler_threads[i].state == THREAD_BLOCKED
 | 
| 260 |  | -         && scheduler_threads[i].timeout != -1
 | 
| 261 |  | -         && TIME_AFTER(usec, scheduler_threads[i].blocked_since
 | 
| 262 |  | -                           + scheduler_threads[i].timeout))
 | 
| 263 |  | -        {
 | 
| 264 |  | -            if (scheduler_threads[i].block_type == THREAD_BLOCK_MUTEX)
 | 
| 265 |  | -                mutex_remove_from_queue((struct mutex*)scheduler_threads[i].blocked_by,
 | 
| 266 |  | -                                        &scheduler_threads[i]);
 | 
| 267 |  | -            scheduler_threads[i].state = THREAD_READY;
 | 
| 268 |  | -            scheduler_threads[i].block_type = THREAD_NOT_BLOCKED;
 | 
| 269 |  | -            scheduler_threads[i].blocked_by = NULL;
 | 
| 270 |  | -            scheduler_threads[i].timeout = 0;
 | 
| 271 |  | -        }
 | 
| 272 |  | -
 | 
| 273 |  | -    if (thread >= 0 && thread < MAX_THREADS && scheduler_threads[thread].state == THREAD_READY)
 | 
| 274 |  | -        current_thread = &scheduler_threads[thread];
 | 
|  | 265 | +    if (scheduler_frozen) thread = 0; | 
| 275 | 266 | else | 
| 276 | 267 | { | 
| 277 |  | -        thread = 0;
 | 
| 278 |  | -        best = 0xffffffff;
 | 
| 279 | 268 | for (i = 0; i < MAX_THREADS; i++) | 
| 280 |  | -            if (scheduler_threads[i].state == THREAD_READY && scheduler_threads[i].priority)
 | 
|  | 269 | +            if (scheduler_threads[i].state == THREAD_BLOCKED | 
|  | 270 | +             && scheduler_threads[i].timeout != -1 | 
|  | 271 | +             && TIME_AFTER(usec, scheduler_threads[i].blocked_since | 
|  | 272 | +                               + scheduler_threads[i].timeout)) | 
| 281 | 273 | { | 
| 282 |  | -                score = scheduler_threads[i].cputime_current / scheduler_threads[i].priority;
 | 
| 283 |  | -                if (score < best)
 | 
|  | 274 | +                if (scheduler_threads[i].block_type == THREAD_BLOCK_MUTEX) | 
|  | 275 | +                    mutex_remove_from_queue((struct mutex*)scheduler_threads[i].blocked_by, | 
|  | 276 | +                                            &scheduler_threads[i]); | 
|  | 277 | +                scheduler_threads[i].state = THREAD_READY; | 
|  | 278 | +                scheduler_threads[i].block_type = THREAD_NOT_BLOCKED; | 
|  | 279 | +                scheduler_threads[i].blocked_by = NULL; | 
|  | 280 | +                scheduler_threads[i].timeout = 0; | 
|  | 281 | +            } | 
|  | 282 | + | 
|  | 283 | +        if (thread >= 0 && thread < MAX_THREADS && scheduler_threads[thread].state == THREAD_READY) | 
|  | 284 | +            current_thread = &scheduler_threads[thread]; | 
|  | 285 | +        else | 
|  | 286 | +        { | 
|  | 287 | +            thread = 0; | 
|  | 288 | +            best = 0xffffffff; | 
|  | 289 | +            for (i = 0; i < MAX_THREADS; i++) | 
|  | 290 | +                if (scheduler_threads[i].state == THREAD_READY && scheduler_threads[i].priority) | 
| 284 | 291 | { | 
| 285 |  | -                    best = score;
 | 
| 286 |  | -                    thread = i;
 | 
|  | 292 | +                    score = scheduler_threads[i].cputime_current / scheduler_threads[i].priority; | 
|  | 293 | +                    if (score < best) | 
|  | 294 | +                    { | 
|  | 295 | +                        best = score; | 
|  | 296 | +                        thread = i; | 
|  | 297 | +                    } | 
| 287 | 298 | } | 
| 288 |  | -            }
 | 
|  | 299 | +        } | 
| 289 | 300 | } | 
| 290 | 301 |  | 
| 291 | 302 | current_thread = &scheduler_threads[thread]; | 
| Index: embios/trunk/usb/usb.c | 
| — | — | @@ -458,6 +458,11 @@ | 
| 459 | 459 | memcpy(&dbgsendbuf[4], scheduler_threads, dbgrecvbuf[1]); | 
| 460 | 460 | size = dbgrecvbuf[1] + 16; | 
| 461 | 461 | break; | 
|  | 462 | +        case 16:  // FREEZE SCHEDULER | 
|  | 463 | +            scheduler_freeze(dbgrecvbuf[1]); | 
|  | 464 | +            dbgsendbuf[0] = 1; | 
|  | 465 | +            size = 16; | 
|  | 466 | +            break; | 
| 462 | 467 | default: | 
| 463 | 468 | dbgsendbuf[0] = 2; | 
| 464 | 469 | size = 16; | 
| Index: embios/trunk/thread.h | 
| — | — | @@ -106,6 +106,7 @@ | 
| 107 | 107 |  | 
| 108 | 108 | void scheduler_init() INITCODE_ATTR; | 
| 109 | 109 | void scheduler_switch(int thread) ICODE_ATTR; | 
|  | 110 | +void scheduler_freeze(bool value); | 
| 110 | 111 | int thread_create(const char* name, const void* code, void* stack, | 
| 111 | 112 | int stacksize, enum thread_type type, int priority, bool run); | 
| 112 | 113 | int thread_suspend(int thread); |