f9micro / f9-kernel

An efficient and secure microkernel built for ARM Cortex-M cores, inspired by L4
Other
679 stars 145 forks source link

pthread_mutex_lock stuck when acquiring a locked mutex #124

Open louisom opened 7 years ago

louisom commented 7 years ago

assume ping and pong thread was create, and have following code.

ping_thread

__USER_TEXT
void *ping_thread(void *arg)
{
    pthread_mutex_lock(&p);
        printf("PING...\n");

    value = 10;
    L4_Sleep(L4_TimePeriod(1000 * 1000));
    printf("I'm a sleepy man\n");
    pthread_mutex_unlock(&p);
    return NULL;
}

pong_thread

__USER_TEXT
void *pong_thread(void *arg)
{
    pthread_mutex_lock(&p);
    value = 20;
        printf("PONG...\n");
        pthread_mutex_unlock(&p);
    return NULL;
}

main

pager_start_thread(threads[PING_THREAD], ping_thread, NULL);
pager_start_thread(threads[PONG_THREAD], pong_thread, NULL);

we will get this result, after pong acquire mutex, it stuck in busy loop.

====================================================
 Copyright(C) 2013-2014 The F9 Microkernel Project  
====================================================
Git head: 58348872e98a7f833cd07690b086d7fa5abd8151
Host: x86_64
Build: 2016-10-04T21:50:39+0800

Press '?' to print KDB menu
PING: 10 1

## KDB ##

but if I add sleep for test, it work again.

__USER_TEXT int pthread_mutex_lock(pthread_mutex_t *mutex)
{
    /* Busy trying */
    while (pthread_mutex_trylock(mutex)) {
        L4_Sleep(L4_TimePeriod(1000));
    }

    return 0;
}

result

====================================================
 Copyright(C) 2013-2014 The F9 Microkernel Project  
====================================================
Git head: 58348872e98a7f833cd07690b086d7fa5abd8151
Host: x86_64
Build: 2016-10-04T21:50:39+0800

Press '?' to print KDB menu
PING: 10 1
I'm a sleepy man
PONG: 20 1

## KDB ##

I'll try to fix this. or maybe this just a recursive lock?

louisom commented 7 years ago

According to p24 in this slide, thread in same priority is execute in round robin scheduling, but somehow if thread was in the busy loop, this scheduler will hang in that loop.

Also found this problem in F9-Kernel-Node where lazy y says

只是基本 kernel, idle, root, normal的priority, Normal threads當中没有priority概念,
也没有公平分配時間,會導致 thread starvation. Example: 
pingpong裡面加入新thread,只做while(1) i++; ,並且在 ping&pong之前create,
會導致ping&pong無法执行。