Changeset 80649a91 in mainline for libc/generic/psthread.c


Ignore:
Timestamp:
2006-05-21T19:28:37Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a410beb
Parents:
1ee11f4
Message:

Merged libadt into libc.
Made lot of psthread and thread stuff thread-safe.
Added new driver framework for easy C connection programming.
Changed FB code to use new API.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libc/generic/psthread.c

    r1ee11f4 r80649a91  
    3434#include <stdio.h>
    3535#include <kernel/arch/faddr.h>
    36 
     36#include <futex.h>
     37#include <assert.h>
    3738
    3839#ifndef PSTHREAD_INITIAL_STACK_PAGES_NO
     
    4142
    4243static LIST_INITIALIZE(ready_list);
     44static LIST_INITIALIZE(manager_list);
    4345
    4446static void psthread_exit(void) __attribute__ ((noinline));
    4547static void psthread_main(void);
    4648
     49static atomic_t psthread_futex = FUTEX_INITIALIZER;
     50
    4751/** Setup PSthread information into TCB structure */
    48 psthread_data_t * psthread_setup(tcb_t *tcb)
    49 {
    50         psthread_data_t *pt;
     52psthread_data_t * psthread_setup()
     53{
     54        psthread_data_t *pt;
     55        tcb_t *tcb;
     56
     57        tcb = __make_tls();
     58        if (!tcb)
     59                return NULL;
    5160
    5261        pt = malloc(sizeof(*pt));
    5362        if (!pt) {
     63                __free_tls(tcb);
    5464                return NULL;
    5565        }
     
    6373void psthread_teardown(psthread_data_t *pt)
    6474{
     75        __free_tls(pt->tcb);
    6576        free(pt);
    6677}
     
    7384        psthread_data_t *pt;
    7485
    75         if (list_empty(&ready_list)) {
    76                 /* Wait on IPC queue etc... */
    77                 printf("Cannot exit!!!\n");
     86        futex_down(&psthread_futex);
     87
     88        if (!list_empty(&ready_list))
     89                pt = list_get_instance(ready_list.next, psthread_data_t, link);
     90        else if (!list_empty(&manager_list))
     91                pt = list_get_instance(manager_list.next, psthread_data_t, link);
     92        else {
     93                printf("Cannot find suitable psthread to run.\n");
    7894                _exit(0);
    7995        }
    80         pt = list_get_instance(ready_list.next, psthread_data_t, link);
    8196        list_remove(&pt->link);
     97        futex_up(&psthread_futex);
     98
    8299        context_restore(&pt->ctx);
     100        /* Never reached */
    83101}
    84102
     
    99117/** Schedule next userspace pseudo thread.
    100118 *
     119 * @param tomanager If true, we are switching to next ready manager thread
     120 *                  (if none is found, thread is exited)
     121 * @param frommanager If true, we are switching from manager thread
    101122 * @return 0 if there is no ready pseudo thread, 1 otherwise.
    102123 */
    103 int psthread_schedule_next(void)
    104 {
    105         psthread_data_t *pt;
    106 
    107         if (list_empty(&ready_list))
    108                 return 0;
     124int psthread_schedule_next_adv(pschange_type ctype)
     125{
     126        psthread_data_t *pt;
     127        int retval = 0;
     128       
     129        futex_down(&psthread_futex);
     130
     131        if (ctype == PS_PREEMPT && list_empty(&ready_list))
     132                goto ret_0;
     133
     134        if (ctype == PS_FROM_MANAGER && list_empty(&ready_list)) {
     135                goto ret_0;
     136        }
     137        assert(!(ctype == PS_TO_MANAGER && list_empty(&manager_list)));
    109138
    110139        pt = __tcb_get()->pst_data;
    111         if (!context_save(&pt->ctx))
    112                 return 1;
     140        if (!context_save(&pt->ctx))
     141                return 1; // futex_up already done here
     142
     143        if (ctype == PS_PREEMPT)
     144                list_append(&pt->link, &ready_list);
     145        else if (ctype == PS_FROM_MANAGER)
     146                list_append(&pt->link, &manager_list);
    113147       
    114         list_append(&pt->link, &ready_list);
    115         pt = list_get_instance(ready_list.next, psthread_data_t, link);
     148        if (ctype == PS_TO_MANAGER)
     149                pt = list_get_instance(manager_list.next,psthread_data_t, link);
     150        else
     151                pt = list_get_instance(ready_list.next, psthread_data_t, link);
    116152        list_remove(&pt->link);
    117153
     154        futex_up(&psthread_futex);
    118155        context_restore(&pt->ctx);
     156
     157ret_0:
     158        futex_up(&psthread_futex);
     159        return retval;
    119160}
    120161
     
    143184
    144185        free(pt->stack);
    145         __free_tls(pt->tcb);
    146186        psthread_teardown((void *)pt);
    147187
     
    150190
    151191/**
    152  * Create a userspace thread and append it to ready list.
     192 * Create a userspace thread
    153193 *
    154194 * @param func Pseudo thread function.
     
    160200{
    161201        psthread_data_t *pt;
    162         tcb_t *tcb;
    163 
    164         tcb = __make_tls();
    165         if (!tcb)
     202
     203        pt = psthread_setup();
     204        if (!pt)
    166205                return 0;
    167 
    168         pt = psthread_setup(tcb);
    169         if (!pt) {
    170                 __free_tls(tcb);
    171                 return 0;
    172         }
    173206        pt->stack = (char *) malloc(PSTHREAD_INITIAL_STACK_PAGES_NO*getpagesize());
    174207
    175208        if (!pt->stack) {
    176                 __free_tls(tcb);
    177209                psthread_teardown(pt);
    178210                return 0;
     
    186218        context_save(&pt->ctx);
    187219        context_set(&pt->ctx, FADDR(psthread_main), pt->stack, PSTHREAD_INITIAL_STACK_PAGES_NO*getpagesize(),
    188                     tcb);
    189 
     220                    pt->tcb);
     221
     222        return (pstid_t )pt;
     223}
     224
     225/** Add a thread to ready list */
     226void psthread_add_ready(pstid_t psthrid)
     227{
     228        psthread_data_t *pt;
     229
     230        pt = (psthread_data_t *) psthrid;
     231        futex_down(&psthread_futex);
    190232        list_append(&pt->link, &ready_list);
    191 
    192         return (pstid_t )pt;
    193 }
     233        futex_up(&psthread_futex);
     234}
     235
     236/** Add a thread to manager list */
     237void psthread_add_manager(pstid_t psthrid)
     238{
     239        psthread_data_t *pt;
     240
     241        pt = (psthread_data_t *) psthrid;
     242
     243        futex_down(&psthread_futex);
     244        list_append(&pt->link, &manager_list);
     245        futex_up(&psthread_futex);
     246}
     247
     248/** Remove one manager from manager list */
     249void psthread_remove_manager()
     250{
     251        futex_down(&psthread_futex);
     252        if (list_empty(&manager_list)) {
     253                printf("No manager found!.\n");
     254                futex_up(&psthread_futex);
     255                return;
     256        }
     257        list_remove(manager_list.next);
     258        futex_up(&psthread_futex);
     259}
Note: See TracChangeset for help on using the changeset viewer.