Numworks Epsilon  1.4.1
Graphing Calculator Operating System
scheduler.c
Go to the documentation of this file.
1 /*
2  * This file is part of the MicroPython project, http://micropython.org/
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2017 Damien P. George
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 
27 #include <stdio.h>
28 
29 #include "py/runtime.h"
30 
31 #if MICROPY_ENABLE_SCHEDULER
32 
33 // A variant of this is inlined in the VM at the pending exception check
34 void mp_handle_pending(void) {
35  if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
36  mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
37  mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
38  if (obj != MP_OBJ_NULL) {
39  MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
40  if (!mp_sched_num_pending()) {
41  MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
42  }
43  MICROPY_END_ATOMIC_SECTION(atomic_state);
44  nlr_raise(obj);
45  }
46  mp_handle_pending_tail(atomic_state);
47  }
48 }
49 
50 // This function should only be called be mp_sched_handle_pending,
51 // or by the VM's inlined version of that function.
52 void mp_handle_pending_tail(mp_uint_t atomic_state) {
53  MP_STATE_VM(sched_state) = MP_SCHED_LOCKED;
54  if (MP_STATE_VM(sched_sp) > 0) {
55  mp_sched_item_t item = MP_STATE_VM(sched_stack)[--MP_STATE_VM(sched_sp)];
56  MICROPY_END_ATOMIC_SECTION(atomic_state);
58  } else {
59  MICROPY_END_ATOMIC_SECTION(atomic_state);
60  }
61  mp_sched_unlock();
62 }
63 
64 void mp_sched_lock(void) {
65  mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
66  if (MP_STATE_VM(sched_state) < 0) {
67  --MP_STATE_VM(sched_state);
68  } else {
69  MP_STATE_VM(sched_state) = MP_SCHED_LOCKED;
70  }
71  MICROPY_END_ATOMIC_SECTION(atomic_state);
72 }
73 
74 void mp_sched_unlock(void) {
75  mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
76  if (++MP_STATE_VM(sched_state) == 0) {
77  // vm became unlocked
78  if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL || mp_sched_num_pending()) {
79  MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
80  } else {
81  MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
82  }
83  }
84  MICROPY_END_ATOMIC_SECTION(atomic_state);
85 }
86 
87 bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg) {
88  mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
89  bool ret;
90  if (MP_STATE_VM(sched_sp) < MICROPY_SCHEDULER_DEPTH) {
91  if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
92  MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
93  }
94  MP_STATE_VM(sched_stack)[MP_STATE_VM(sched_sp)].func = function;
95  MP_STATE_VM(sched_stack)[MP_STATE_VM(sched_sp)].arg = arg;
96  ++MP_STATE_VM(sched_sp);
97  ret = true;
98  } else {
99  // schedule stack is full
100  ret = false;
101  }
102  MICROPY_END_ATOMIC_SECTION(atomic_state);
103  return ret;
104 }
105 
106 #else // MICROPY_ENABLE_SCHEDULER
107 
108 // A variant of this is inlined in the VM at the pending exception check
109 void mp_handle_pending(void) {
110  if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
111  mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
112  MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
113  nlr_raise(obj);
114  }
115 }
116 
117 #endif // MICROPY_ENABLE_SCHEDULER
uintptr_t mp_uint_t
Definition: mpconfigport.h:74
#define MP_STATE_VM(x)
Definition: mpstate.h:241
#define MICROPY_SCHEDULER_DEPTH
Definition: mpconfig.h:658
#define MP_SCHED_LOCKED
Definition: mpstate.h:55
#define MP_SCHED_IDLE
Definition: mpstate.h:54
#define MICROPY_BEGIN_ATOMIC_SECTION()
Definition: mpconfig.h:1169
#define MP_OBJ_NULL
Definition: obj.h:73
mp_obj_t func
Definition: mpstate.h:59
mp_obj_t arg
Definition: mpstate.h:60
#define nlr_raise(val)
Definition: nlr.h:89
#define MICROPY_END_ATOMIC_SECTION(state)
Definition: mpconfig.h:1172
void mp_handle_pending_tail(mp_uint_t atomic_state)
#define MP_SCHED_PENDING
Definition: mpstate.h:56
uint64_t mp_obj_t
Definition: obj.h:39
void mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg)
Definition: runtime_utils.c:30
void mp_handle_pending(void)
Definition: scheduler.c:109