Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 78192cc7 in mainline


Ignore:
Timestamp:
2014-07-13T14:06:23Z (6 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
af2a76c, f303f2cf
Parents:
c1b979a
Message:

Fibril timer locking improvements.

Location:
uspace
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/vlaunch/vlaunch.c

    rc1b979a r78192cc7  
    200200        }
    201201       
    202         timer = fibril_timer_create();
     202        timer = fibril_timer_create(NULL);
    203203        if (!timer) {
    204204                printf("Unable to create timer.\n");
  • uspace/lib/c/generic/fibril_synch.c

    rc1b979a r78192cc7  
    448448        int rc;
    449449
    450         fibril_mutex_lock(&timer->lock);
     450        fibril_mutex_lock(timer->lockp);
    451451
    452452        while (timer->state != fts_cleanup) {
     
    454454                case fts_not_set:
    455455                case fts_fired:
    456                         fibril_condvar_wait(&timer->cv, &timer->lock);
     456                        fibril_condvar_wait(&timer->cv, timer->lockp);
    457457                        break;
    458458                case fts_active:
    459459                        rc = fibril_condvar_wait_timeout(&timer->cv,
    460                             &timer->lock, timer->delay);
     460                            timer->lockp, timer->delay);
    461461                        if (rc == ETIMEOUT && timer->state == fts_active) {
    462462                                timer->state = fts_fired;
    463                                 fibril_mutex_unlock(&timer->lock);
     463                                timer->handler_running = true;
     464                                fibril_mutex_unlock(timer->lockp);
    464465                                timer->fun(timer->arg);
    465                                 fibril_mutex_lock(&timer->lock);
     466                                fibril_mutex_lock(timer->lockp);
     467                                timer->handler_running = false;
    466468                        }
    467469                        break;
     
    475477        /* Acknowledge timer fibril has finished cleanup. */
    476478        timer->state = fts_clean;
    477         fibril_condvar_broadcast(&timer->cv);
    478         fibril_mutex_unlock(&timer->lock);
     479        fibril_mutex_unlock(timer->lockp);
     480        free(timer);
    479481
    480482        return 0;
     
    485487 * @return              New timer on success, @c NULL if out of memory.
    486488 */
    487 fibril_timer_t *fibril_timer_create(void)
     489fibril_timer_t *fibril_timer_create(fibril_mutex_t *lock)
    488490{
    489491        fid_t fid;
     
    505507        timer->fibril = fid;
    506508        timer->state = fts_not_set;
     509        timer->lockp = (lock != NULL) ? lock : &timer->lock;
    507510
    508511        fibril_add_ready(fid);
    509 
    510512        return timer;
    511513}
     
    517519void fibril_timer_destroy(fibril_timer_t *timer)
    518520{
    519         fibril_mutex_lock(&timer->lock);
     521        fibril_mutex_lock(timer->lockp);
    520522        assert(timer->state == fts_not_set || timer->state == fts_fired);
    521523
     
    523525        timer->state = fts_cleanup;
    524526        fibril_condvar_broadcast(&timer->cv);
    525 
    526         /* Wait for timer fibril to acknowledge. */
    527         while (timer->state != fts_clean)
    528                 fibril_condvar_wait(&timer->cv, &timer->lock);
    529 
    530         fibril_mutex_unlock(&timer->lock);
     527        fibril_mutex_unlock(timer->lockp);
    531528}
    532529
     
    544541    fibril_timer_fun_t fun, void *arg)
    545542{
    546         fibril_mutex_lock(&timer->lock);
     543        fibril_mutex_lock(timer->lockp);
     544        fibril_timer_set_locked(timer, delay, fun, arg);
     545        fibril_mutex_unlock(timer->lockp);
     546}
     547
     548/** Set locked timer.
     549 *
     550 * Set timer to execute a callback function after the specified
     551 * interval. Must be called when the timer is locked.
     552 *
     553 * @param timer         Timer
     554 * @param delay         Delay in microseconds
     555 * @param fun           Callback function
     556 * @param arg           Argument for @a fun
     557 */
     558void fibril_timer_set_locked(fibril_timer_t *timer, suseconds_t delay,
     559    fibril_timer_fun_t fun, void *arg)
     560{
     561        assert(fibril_mutex_is_locked(timer->lockp));
    547562        assert(timer->state == fts_not_set || timer->state == fts_fired);
    548563        timer->state = fts_active;
     
    551566        timer->arg = arg;
    552567        fibril_condvar_broadcast(&timer->cv);
    553         fibril_mutex_unlock(&timer->lock);
    554568}
    555569
     
    569583        fibril_timer_state_t old_state;
    570584
    571         fibril_mutex_lock(&timer->lock);
     585        fibril_mutex_lock(timer->lockp);
     586        old_state = fibril_timer_clear_locked(timer);
     587        fibril_mutex_unlock(timer->lockp);
     588
     589        return old_state;
     590}
     591
     592/** Clear locked timer.
     593 *
     594 * Clears (cancels) timer and returns last state of the timer.
     595 * This can be one of:
     596 *    - fts_not_set     If the timer has not been set or has been cleared
     597 *    - fts_active      Timer was set but did not fire
     598 *    - fts_fired       Timer fired
     599 * Must be called when the timer is locked.
     600 *
     601 * @param timer         Timer
     602 * @return              Last timer state
     603 */
     604fibril_timer_state_t fibril_timer_clear_locked(fibril_timer_t *timer)
     605{
     606        fibril_timer_state_t old_state;
     607
     608        assert(fibril_mutex_is_locked(timer->lockp));
     609
     610        while (timer->handler_running)
     611                fibril_condvar_wait(&timer->cv, timer->lockp);
     612
    572613        old_state = timer->state;
    573614        timer->state = fts_not_set;
     
    577618        timer->arg = NULL;
    578619        fibril_condvar_broadcast(&timer->cv);
    579         fibril_mutex_unlock(&timer->lock);
    580620
    581621        return old_state;
  • uspace/lib/c/include/fibril_synch.h

    rc1b979a r78192cc7  
    131131typedef struct {
    132132        fibril_mutex_t lock;
     133        fibril_mutex_t *lockp;
    133134        fibril_condvar_t cv;
    134135        fid_t fibril;
    135136        fibril_timer_state_t state;
     137        bool handler_running;
    136138
    137139        suseconds_t delay;
     
    162164extern void fibril_condvar_broadcast(fibril_condvar_t *);
    163165
    164 extern fibril_timer_t *fibril_timer_create(void);
     166extern fibril_timer_t *fibril_timer_create(fibril_mutex_t *);
    165167extern void fibril_timer_destroy(fibril_timer_t *);
    166168extern void fibril_timer_set(fibril_timer_t *, suseconds_t, fibril_timer_fun_t,
    167169    void *);
     170extern void fibril_timer_set_locked(fibril_timer_t *, suseconds_t,
     171    fibril_timer_fun_t, void *);
    168172extern fibril_timer_state_t fibril_timer_clear(fibril_timer_t *);
     173extern fibril_timer_state_t fibril_timer_clear_locked(fibril_timer_t *);
    169174
    170175#endif
  • uspace/srv/net/dhcp/dhcp.c

    rc1b979a r78192cc7  
    436436
    437437        dlink->link_id = link_id;
    438         dlink->timeout = fibril_timer_create();
     438        dlink->timeout = fibril_timer_create(NULL);
    439439        if (dlink->timeout == NULL) {
    440440                rc = ENOMEM;
  • uspace/srv/net/tcp/conn.c

    rc1b979a r78192cc7  
    7878                goto error;
    7979
    80         conn->tw_timer = fibril_timer_create();
     80        fibril_mutex_initialize(&conn->lock);
     81
     82        conn->tw_timer = fibril_timer_create(&conn->lock);
    8183        if (conn->tw_timer == NULL)
    8284                goto error;
    83 
    84         fibril_mutex_initialize(&conn->lock);
    8585
    8686        /* One for the user, one for not being in closed state */
     
    200200        if (atomic_predec(&conn->refcnt) == 0)
    201201                tcp_conn_free(conn);
     202}
     203
     204/** Lock connection.
     205 *
     206 * Must be called before any other connection-manipulating function,
     207 * except tcp_conn_{add|del}ref(). Locks the connection including
     208 * its timers. Must not be called inside any of the connection
     209 * timer handlers.
     210 *
     211 * @param conn          Connection
     212 */
     213void tcp_conn_lock(tcp_conn_t *conn)
     214{
     215        fibril_mutex_lock(&conn->lock);
     216}
     217
     218/** Unlock connection.
     219 *
     220 * @param conn          Connection
     221 */
     222void tcp_conn_unlock(tcp_conn_t *conn)
     223{
     224        fibril_mutex_unlock(&conn->lock);
    202225}
    203226
     
    11831206        log_msg(LOG_DEFAULT, LVL_DEBUG, "tw_timeout_func(%p)", conn);
    11841207
    1185         fibril_mutex_lock(&conn->lock);
     1208        tcp_conn_lock(conn);
    11861209
    11871210        if (conn->cstate == st_closed) {
    11881211                log_msg(LOG_DEFAULT, LVL_DEBUG, "Connection already closed.");
    1189                 fibril_mutex_unlock(&conn->lock);
     1212                tcp_conn_unlock(conn);
    11901213                tcp_conn_delref(conn);
    11911214                return;
     
    11961219        tcp_conn_state_set(conn, st_closed);
    11971220
    1198         fibril_mutex_unlock(&conn->lock);
     1221        tcp_conn_unlock(conn);
    11991222        tcp_conn_delref(conn);
     1223
     1224        log_msg(LOG_DEFAULT, LVL_DEBUG, "tw_timeout_func(%p) end", conn);
    12001225}
    12011226
     
    12061231void tcp_conn_tw_timer_set(tcp_conn_t *conn)
    12071232{
     1233        log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_conn_tw_timer_set() begin");
    12081234        tcp_conn_addref(conn);
    1209         fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
    1210             (void *)conn);
     1235        fibril_timer_set_locked(conn->tw_timer, TIME_WAIT_TIMEOUT,
     1236            tw_timeout_func, (void *)conn);
     1237        log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_conn_tw_timer_set() end");
    12111238}
    12121239
     
    12171244void tcp_conn_tw_timer_clear(tcp_conn_t *conn)
    12181245{
    1219         if (fibril_timer_clear(conn->tw_timer) == fts_active)
     1246        log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_conn_tw_timer_clear() begin");
     1247        if (fibril_timer_clear_locked(conn->tw_timer) == fts_active)
    12201248                tcp_conn_delref(conn);
     1249        log_msg(LOG_DEFAULT, LVL_DEBUG2, "tcp_conn_tw_timer_clear() end");
    12211250}
    12221251
  • uspace/srv/net/tcp/conn.h

    rc1b979a r78192cc7  
    5050extern void tcp_conn_addref(tcp_conn_t *);
    5151extern void tcp_conn_delref(tcp_conn_t *);
     52extern void tcp_conn_lock(tcp_conn_t *);
     53extern void tcp_conn_unlock(tcp_conn_t *);
    5254extern bool tcp_conn_got_syn(tcp_conn_t *);
    5355extern void tcp_conn_segment_arrived(tcp_conn_t *, tcp_segment_t *);
  • uspace/srv/net/tcp/tqueue.c

    rc1b979a r78192cc7  
    5959static void tcp_tqueue_timer_clear(tcp_conn_t *conn);
    6060
     61#include <stdio.h>
    6162int tcp_tqueue_init(tcp_tqueue_t *tqueue, tcp_conn_t *conn)
    6263{
     64        printf("tcp_tqueue_init\n");
    6365        tqueue->conn = conn;
    64         tqueue->timer = fibril_timer_create();
     66        tqueue->timer = fibril_timer_create(&conn->lock);
    6567        if (tqueue->timer == NULL)
    6668                return ENOMEM;
     
    7880void tcp_tqueue_fini(tcp_tqueue_t *tqueue)
    7981{
     82        printf("tcp_tqueue_fini\n");
    8083        if (tqueue->timer != NULL) {
    8184                fibril_timer_destroy(tqueue->timer);
     
    319322        log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn);
    320323
    321         fibril_mutex_lock(&conn->lock);
     324        tcp_conn_lock(conn);
    322325
    323326        if (conn->cstate == st_closed) {
    324327                log_msg(LOG_DEFAULT, LVL_DEBUG, "Connection already closed.");
    325                 fibril_mutex_unlock(&conn->lock);
     328                tcp_conn_unlock(conn);
    326329                tcp_conn_delref(conn);
    327330                return;
     
    331334        if (link == NULL) {
    332335                log_msg(LOG_DEFAULT, LVL_DEBUG, "Nothing to retransmit");
    333                 fibril_mutex_unlock(&conn->lock);
     336                tcp_conn_unlock(conn);
    334337                tcp_conn_delref(conn);
    335338                return;
     
    341344        if (rt_seg == NULL) {
    342345                log_msg(LOG_DEFAULT, LVL_ERROR, "Memory allocation failed.");
    343                 fibril_mutex_unlock(&conn->lock);
     346                tcp_conn_unlock(conn);
    344347                tcp_conn_delref(conn);
    345348                /* XXX Handle properly */
     
    353356        tcp_tqueue_timer_set(tqe->conn);
    354357
    355         fibril_mutex_unlock(&conn->lock);
     358        tcp_conn_unlock(conn);
    356359        tcp_conn_delref(conn);
     360
     361        log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: retransmit_timeout_func(%p) end", conn->name, conn);
    357362}
    358363
     
    360365static void tcp_tqueue_timer_set(tcp_conn_t *conn)
    361366{
    362         log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name);
     367        log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: tcp_tqueue_timer_set() begin", conn->name);
    363368
    364369        /* Clear first to make sure we update refcnt correctly */
     
    366371
    367372        tcp_conn_addref(conn);
    368         fibril_timer_set(conn->retransmit.timer, RETRANSMIT_TIMEOUT,
     373        fibril_timer_set_locked(conn->retransmit.timer, RETRANSMIT_TIMEOUT,
    369374            retransmit_timeout_func, (void *) conn);
     375
     376        log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: tcp_tqueue_timer_set() end", conn->name);
    370377}
    371378
     
    373380static void tcp_tqueue_timer_clear(tcp_conn_t *conn)
    374381{
    375         log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name);
    376 
    377         if (fibril_timer_clear(conn->retransmit.timer) == fts_active)
     382        log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: tcp_tqueue_timer_clear() begin", conn->name);
     383
     384        if (fibril_timer_clear_locked(conn->retransmit.timer) == fts_active)
    378385                tcp_conn_delref(conn);
     386
     387        log_msg(LOG_DEFAULT, LVL_DEBUG, "### %s: tcp_tqueue_timer_clear() end", conn->name);
    379388}
    380389
  • uspace/srv/net/tcp/ucall.c

    rc1b979a r78192cc7  
    9090        /* Wait for connection to be established or reset */
    9191        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open: Wait for connection.");
    92         fibril_mutex_lock(&nconn->lock);
     92        tcp_conn_lock(nconn);
    9393        while (nconn->cstate == st_listen ||
    9494            nconn->cstate == st_syn_sent ||
     
    100100                log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open: Connection was reset.");
    101101                assert(nconn->cstate == st_closed);
    102                 fibril_mutex_unlock(&nconn->lock);
     102                tcp_conn_unlock(nconn);
    103103                return TCP_ERESET;
    104104        }
    105105
    106         fibril_mutex_unlock(&nconn->lock);
     106        tcp_conn_unlock(nconn);
    107107        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_open: Connection was established.");
    108108
     
    121121        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_uc_send()", conn->name);
    122122
    123         fibril_mutex_lock(&conn->lock);
     123        tcp_conn_lock(conn);
    124124
    125125        if (conn->cstate == st_closed) {
    126                 fibril_mutex_unlock(&conn->lock);
     126                tcp_conn_unlock(conn);
    127127                return TCP_ENOTEXIST;
    128128        }
     
    135135
    136136        if (conn->snd_buf_fin) {
    137                 fibril_mutex_unlock(&conn->lock);
     137                tcp_conn_unlock(conn);
    138138                return TCP_ECLOSING;
    139139        }
     
    149149
    150150                if (conn->reset) {
    151                         fibril_mutex_unlock(&conn->lock);
     151                        tcp_conn_unlock(conn);
    152152                        return TCP_ERESET;
    153153                }
     
    165165
    166166        tcp_tqueue_new_data(conn);
    167         fibril_mutex_unlock(&conn->lock);
     167        tcp_conn_unlock(conn);
    168168
    169169        return TCP_EOK;
     
    178178        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_uc_receive()", conn->name);
    179179
    180         fibril_mutex_lock(&conn->lock);
     180        tcp_conn_lock(conn);
    181181
    182182        if (conn->cstate == st_closed) {
    183                 fibril_mutex_unlock(&conn->lock);
     183                tcp_conn_unlock(conn);
    184184                return TCP_ENOTEXIST;
    185185        }
     
    197197                if (conn->rcv_buf_fin) {
    198198                        /* End of data, peer closed connection */
    199                         fibril_mutex_unlock(&conn->lock);
     199                        tcp_conn_unlock(conn);
    200200                        return TCP_ECLOSING;
    201201                } else {
    202202                        /* Connection was reset */
    203203                        assert(conn->reset);
    204                         fibril_mutex_unlock(&conn->lock);
     204                        tcp_conn_unlock(conn);
    205205                        return TCP_ERESET;
    206206                }
     
    227227            conn->name, xfer_size);
    228228
    229         fibril_mutex_unlock(&conn->lock);
     229        tcp_conn_unlock(conn);
    230230
    231231        return TCP_EOK;
     
    238238            conn);
    239239
    240         fibril_mutex_lock(&conn->lock);
     240        tcp_conn_lock(conn);
    241241
    242242        if (conn->cstate == st_closed) {
    243243                log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_close - ENOTEXIST");
    244                 fibril_mutex_unlock(&conn->lock);
     244                tcp_conn_unlock(conn);
    245245                return TCP_ENOTEXIST;
    246246        }
     
    250250                tcp_conn_reset(conn);
    251251                tcp_conn_remove(conn);
     252                tcp_conn_unlock(conn);
    252253                return TCP_EOK;
    253254        }
     
    255256        if (conn->snd_buf_fin) {
    256257                log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_uc_close - ECLOSING");
    257                 fibril_mutex_unlock(&conn->lock);
     258                tcp_conn_unlock(conn);
    258259                return TCP_ECLOSING;
    259260        }
     
    263264        tcp_tqueue_new_data(conn);
    264265
    265         fibril_mutex_unlock(&conn->lock);
     266        tcp_conn_unlock(conn);
    266267        return TCP_EOK;
    267268}
     
    321322        }
    322323
    323         fibril_mutex_lock(&conn->lock);
     324        tcp_conn_lock(conn);
    324325
    325326        if (conn->cstate == st_closed) {
    326327                log_msg(LOG_DEFAULT, LVL_WARN, "Connection is closed.");
    327328                tcp_unexpected_segment(sp, seg);
    328                 fibril_mutex_unlock(&conn->lock);
     329                tcp_conn_unlock(conn);
    329330                tcp_conn_delref(conn);
    330331                return;
     
    342343        tcp_conn_segment_arrived(conn, seg);
    343344
    344         fibril_mutex_unlock(&conn->lock);
     345        tcp_conn_unlock(conn);
    345346        tcp_conn_delref(conn);
    346347}
Note: See TracChangeset for help on using the changeset viewer.