Subversion Repositories HelenOS

Rev

Rev 2492 | Rev 3049 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2492 Rev 2568
Line 73... Line 73...
73
 
73
 
74
    tcb = __make_tls();
74
    tcb = __make_tls();
75
    if (!tcb)
75
    if (!tcb)
76
        return NULL;
76
        return NULL;
77
 
77
 
78
    f = malloc(sizeof(*f));
78
    f = malloc(sizeof(fibril_t));
79
    if (!f) {
79
    if (!f) {
80
        __free_tls(tcb);
80
        __free_tls(tcb);
81
        return NULL;
81
        return NULL;
82
    }
82
    }
83
 
83
 
84
    tcb->fibril_data = f;
84
    tcb->fibril_data = f;
85
    f->tcb = tcb;
85
    f->tcb = tcb;
86
 
86
 
-
 
87
    f->func = NULL;
-
 
88
    f->arg = NULL;
-
 
89
    f->stack = NULL;
-
 
90
    f->clean_after_me = NULL;
-
 
91
    f->retval = 0;
-
 
92
    f->flags = 0;
-
 
93
 
87
    return f;
94
    return f;
88
}
95
}
89
 
96
 
90
void fibril_teardown(fibril_t *f)
97
void fibril_teardown(fibril_t *f)
91
{
98
{
Line 104... Line 111...
104
    fibril_t *f = __tcb_get()->fibril_data;
111
    fibril_t *f = __tcb_get()->fibril_data;
105
 
112
 
106
    /* Call the implementing function. */
113
    /* Call the implementing function. */
107
    f->retval = f->func(f->arg);
114
    f->retval = f->func(f->arg);
108
 
115
 
109
    fibril_schedule_next_adv(FIBRIL_FROM_DEAD);
116
    fibril_switch(FIBRIL_FROM_DEAD);
110
    /* not reached */
117
    /* not reached */
111
}
118
}
112
 
119
 
113
/** Schedule next fibril.
120
/** Switch from the current fibril.
114
 *
121
 *
115
 * If calling with FIBRIL_TO_MANAGER parameter, the async_futex should be
122
 * If calling with FIBRIL_TO_MANAGER parameter, the async_futex should be
116
 * held.
123
 * held.
117
 *
124
 *
118
 * @param stype     Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER,
125
 * @param stype     Switch type. One of FIBRIL_PREEMPT, FIBRIL_TO_MANAGER,
119
 *          FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter
126
 *          FIBRIL_FROM_MANAGER, FIBRIL_FROM_DEAD. The parameter
120
 *          describes the circumstances of the switch.
127
 *          describes the circumstances of the switch.
121
 * @return      Return 0 if there is no ready fibril,
128
 * @return      Return 0 if there is no ready fibril,
122
 *          return 1 otherwise.
129
 *          return 1 otherwise.
123
 */
130
 */
124
int fibril_schedule_next_adv(fibril_switch_type_t stype)
131
int fibril_switch(fibril_switch_type_t stype)
125
{
132
{
126
    fibril_t *srcf, *dstf;
133
    fibril_t *srcf, *dstf;
127
    int retval = 0;
134
    int retval = 0;
128
   
135
   
129
    futex_down(&fibril_futex);
136
    futex_down(&fibril_futex);
Line 136... Line 143...
136
            goto ret_0;
143
            goto ret_0;
137
        /*
144
        /*
138
         * Do not preempt if there is not sufficient count of fibril
145
         * Do not preempt if there is not sufficient count of fibril
139
         * managers.
146
         * managers.
140
         */
147
         */
141
        if (list_empty(&serialized_list) && fibrils_in_manager <=
148
        if (list_empty(&serialized_list) &&
142
            serialized_fibrils) {
149
            fibrils_in_manager <= serialized_fibrils) {
143
            goto ret_0;
150
            goto ret_0;
144
        }
151
        }
145
    }
152
    }
146
    /* If we are going to manager and none exists, create it */
153
    /* If we are going to manager and none exists, create it */
147
    if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
154
    if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
Line 161... Line 168...
161
            if (srcf->clean_after_me) {
168
            if (srcf->clean_after_me) {
162
                /*
169
                /*
163
                 * Cleanup after the dead fibril from which we
170
                 * Cleanup after the dead fibril from which we
164
                 * restored context here.
171
                 * restored context here.
165
                 */
172
                 */
166
                free(srcf->clean_after_me->stack);
173
                void *stack = srcf->clean_after_me->stack;
-
 
174
                if (stack) {
-
 
175
                    /*
-
 
176
                     * This check is necessary because a
-
 
177
                     * thread could have exited like a
-
 
178
                     * normal fibril using the
-
 
179
                     * FIBRIL_FROM_DEAD switch type. In that
-
 
180
                     * case, its fibril will not have the
-
 
181
                     * stack member filled.
-
 
182
                     */
-
 
183
                    free(stack);
-
 
184
                }
167
                fibril_teardown(srcf->clean_after_me);
185
                fibril_teardown(srcf->clean_after_me);
168
                srcf->clean_after_me = NULL;
186
                srcf->clean_after_me = NULL;
169
            }
187
            }
170
            return 1;   /* futex_up already done here */
188
            return 1;   /* futex_up already done here */
171
        }
189
        }
Line 182... Line 200...
182
             * any list, we should already be somewhere, or we will
200
             * any list, we should already be somewhere, or we will
183
             * be lost.
201
             * be lost.
184
             */
202
             */
185
        }
203
        }
186
    }
204
    }
187
 
205
   
188
    /* Choose a new fibril to run */
206
    /* Choose a new fibril to run */
189
    if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
207
    if (stype == FIBRIL_TO_MANAGER || stype == FIBRIL_FROM_DEAD) {
190
        dstf = list_get_instance(manager_list.next, fibril_t, link);
208
        dstf = list_get_instance(manager_list.next, fibril_t, link);
191
        if (serialization_count && stype == FIBRIL_TO_MANAGER) {
209
        if (serialization_count && stype == FIBRIL_TO_MANAGER) {
192
            serialized_fibrils++;
210
            serialized_fibrils++;
193
            srcf->flags |= FIBRIL_SERIALIZED;
211
            srcf->flags |= FIBRIL_SERIALIZED;
194
        }
212
        }
195
        fibrils_in_manager++;
213
        fibrils_in_manager++;
196
 
214
 
197
        if (stype == FIBRIL_FROM_DEAD)
215
        if (stype == FIBRIL_FROM_DEAD)
198
            dstf->clean_after_me = srcf;
216
            dstf->clean_after_me = srcf;
199
    } else {
217
    } else {
200
        if (!list_empty(&serialized_list)) {
218
        if (!list_empty(&serialized_list)) {
201
            dstf = list_get_instance(serialized_list.next, fibril_t,
219
            dstf = list_get_instance(serialized_list.next, fibril_t,
202
                link);
220
                link);
Line 231... Line 249...
231
    f = fibril_setup();
249
    f = fibril_setup();
232
    if (!f)
250
    if (!f)
233
        return 0;
251
        return 0;
234
    f->stack = (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO *
252
    f->stack = (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO *
235
        getpagesize());
253
        getpagesize());
236
 
-
 
237
    if (!f->stack) {
254
    if (!f->stack) {
238
        fibril_teardown(f);
255
        fibril_teardown(f);
239
        return 0;
256
        return 0;
240
    }
257
    }
241
 
258
   
242
    f->arg = arg;
-
 
243
    f->func = func;
259
    f->func = func;
244
    f->clean_after_me = NULL;
-
 
245
    f->retval = 0;
-
 
246
    f->flags = 0;
260
    f->arg = arg;
247
 
261
 
248
    context_save(&f->ctx);
262
    context_save(&f->ctx);
249
    context_set(&f->ctx, FADDR(fibril_main), f->stack,
263
    context_set(&f->ctx, FADDR(fibril_main), f->stack,
250
        FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), f->tcb);
264
        FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), f->tcb);
251
 
265