Changeset 2a3214e in mainline


Ignore:
Timestamp:
2011-10-26T16:50:52Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8218b6b
Parents:
6e88fea
Message:

Fibril timer primitive.
TCP Time-Wait timeout.

Location:
uspace
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/fibril_synch.c

    r6e88fea r2a3214e  
    447447}
    448448
     449/** Timer fibril.
     450 *
     451 * @param arg   Timer
     452 */
     453static int fibril_timer_func(void *arg)
     454{
     455        fibril_timer_t *timer = (fibril_timer_t *) arg;
     456        int rc;
     457
     458        fibril_mutex_lock(&timer->lock);
     459
     460        while (true) {
     461                while (timer->state != fts_active &&
     462                    timer->state != fts_cleanup) {
     463
     464                        if (timer->state == fts_cleanup)
     465                                break;
     466
     467                        fibril_condvar_wait(&timer->cv, &timer->lock);
     468                }
     469
     470                if (timer->state == fts_cleanup)
     471                        break;
     472
     473                rc = fibril_condvar_wait_timeout(&timer->cv, &timer->lock,
     474                    timer->delay);
     475                if (rc == ETIMEOUT) {
     476                        timer->fun(timer->arg);
     477                        timer->state = fts_fired;
     478                }
     479        }
     480
     481        fibril_mutex_unlock(&timer->lock);
     482        return 0;
     483}
     484
     485/** Create new timer.
     486 *
     487 * @return              New timer on success, @c NULL if out of memory.
     488 */
     489fibril_timer_t *fibril_timer_create(void)
     490{
     491        fid_t fid;
     492        fibril_timer_t *timer;
     493
     494        timer = calloc(1, sizeof(fibril_timer_t));
     495        if (timer == NULL)
     496                return NULL;
     497
     498        fid = fibril_create(fibril_timer_func, (void *) timer);
     499        if (fid == 0) {
     500                free(timer);
     501                return NULL;
     502        }
     503
     504        fibril_mutex_initialize(&timer->lock);
     505        fibril_condvar_initialize(&timer->cv);
     506
     507        timer->fibril = fid;
     508        timer->state = fts_not_set;
     509
     510        fibril_add_ready(fid);
     511
     512        return timer;
     513}
     514
     515/** Destroy timer.
     516 *
     517 * @param timer         Timer, must not be active or accessed by other threads.
     518 */
     519void fibril_timer_destroy(fibril_timer_t *timer)
     520{
     521        fibril_mutex_lock(&timer->lock);
     522        assert(timer->state != fts_active);
     523        timer->state = fts_cleanup;
     524        fibril_condvar_broadcast(&timer->cv);
     525        fibril_mutex_unlock(&timer->lock);
     526}
     527
     528/** Set timer.
     529 *
     530 * Set timer to execute a callback function after the specified
     531 * interval.
     532 *
     533 * @param timer         Timer
     534 * @param delay         Delay in microseconds
     535 * @param fun           Callback function
     536 * @param arg           Argument for @a fun
     537 */
     538void fibril_timer_set(fibril_timer_t *timer, suseconds_t delay,
     539    fibril_timer_fun_t fun, void *arg)
     540{
     541        fibril_mutex_lock(&timer->lock);
     542        timer->state = fts_active;
     543        timer->delay = delay;
     544        timer->fun = fun;
     545        timer->arg = arg;
     546        fibril_condvar_broadcast(&timer->cv);
     547        fibril_mutex_unlock(&timer->lock);
     548}
     549
     550/** Clear timer.
     551 *
     552 * Clears (cancels) timer and returns last state of the timer.
     553 * This can be one of:
     554 *    - fts_not_set     If the timer has not been set or has been cleared
     555 *    - fts_active      Timer was set but did not fire
     556 *    - fts_fired       Timer fired
     557 *
     558 * @param timer         Timer
     559 * @return              Last timer state
     560 */
     561fibril_timer_state_t fibril_timer_clear(fibril_timer_t *timer)
     562{
     563        fibril_timer_state_t old_state;
     564
     565        fibril_mutex_lock(&timer->lock);
     566        old_state = timer->state;
     567        timer->state = fts_not_set;
     568
     569        timer->delay = 0;
     570        timer->fun = NULL;
     571        timer->arg = NULL;
     572        fibril_condvar_broadcast(&timer->cv);
     573        fibril_mutex_unlock(&timer->lock);
     574
     575        return old_state;
     576}
     577
    449578/** @}
    450579 */
  • uspace/lib/c/include/fibril_synch.h

    r6e88fea r2a3214e  
    107107        fibril_condvar_t name = FIBRIL_CONDVAR_INITIALIZER(name)
    108108
     109typedef void (*fibril_timer_fun_t)(void *);
     110
     111typedef enum {
     112        /** Timer has not been set or has been cleared */
     113        fts_not_set,
     114        /** Timer was set but did not fire yet */
     115        fts_active,
     116        /** Timer has fired and has not been cleared since */
     117        fts_fired,
     118        /** Timer is being destroyed */
     119        fts_cleanup
     120} fibril_timer_state_t;
     121
     122/** Fibril timer.
     123 *
     124 * When a timer is set it executes a callback function (in a separate
     125 * fibril) after a specified time interval. The timer can be cleared
     126 * (canceled) before that. From the return value of fibril_timer_clear()
     127 * one can tell whether the timer fired or not.
     128 */
     129typedef struct {
     130        fibril_mutex_t lock;
     131        fibril_condvar_t cv;
     132        fid_t fibril;
     133        fibril_timer_state_t state;
     134
     135        suseconds_t delay;
     136        fibril_timer_fun_t fun;
     137        void *arg;
     138} fibril_timer_t;
     139
    109140extern void fibril_mutex_initialize(fibril_mutex_t *);
    110141extern void fibril_mutex_lock(fibril_mutex_t *);
     
    129160extern void fibril_condvar_broadcast(fibril_condvar_t *);
    130161
     162extern fibril_timer_t *fibril_timer_create(void);
     163extern void fibril_timer_destroy(fibril_timer_t *);
     164extern void fibril_timer_set(fibril_timer_t *, suseconds_t, fibril_timer_fun_t,
     165    void *);
     166extern fibril_timer_state_t fibril_timer_clear(fibril_timer_t *);
     167
    131168#endif
    132169
  • uspace/srv/net/tl/tcp/conn.c

    r6e88fea r2a3214e  
    4545#include "segment.h"
    4646#include "seq_no.h"
     47#include "state.h"
    4748#include "tcp_type.h"
    4849#include "tqueue.h"
     
    5152#define SND_BUF_SIZE 4096
    5253
     54#define MAX_SEGMENT_LIFETIME    (15*1000*1000) //(2*60*1000*1000)
     55#define TIME_WAIT_TIMEOUT       (2*MAX_SEGMENT_LIFETIME)
     56
    5357LIST_INITIALIZE(conn_list);
    5458
    5559static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
     60static void tcp_conn_tw_timer_set(tcp_conn_t *conn);
    5661
    5762/** Create new segment structure.
     
    6368tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock)
    6469{
    65         tcp_conn_t *conn;
     70        tcp_conn_t *conn = NULL;
    6671
    6772        /* Allocate connection structure */
    6873        conn = calloc(1, sizeof(tcp_conn_t));
    6974        if (conn == NULL)
    70                 return NULL;
     75                goto error;
     76
     77        conn->tw_timer = fibril_timer_create();
     78        if (conn->tw_timer == NULL)
     79                goto error;
    7180
    7281        /* Allocate receive buffer */
     
    7887
    7988        conn->rcv_buf = calloc(1, conn->rcv_buf_size);
    80         if (conn->rcv_buf == NULL) {
    81                 free(conn);
    82                 return NULL;
    83         }
     89        if (conn->rcv_buf == NULL)
     90                goto error;
    8491
    8592        /** Allocate send buffer */
     
    8895        conn->snd_buf_fin = false;
    8996        conn->snd_buf = calloc(1, conn->snd_buf_size);
    90         if (conn->snd_buf == NULL) {
    91                 free(conn);
    92                 return NULL;
    93         }
     97        if (conn->snd_buf == NULL)
     98                goto error;
    9499
    95100        /* Set up receive window. */
     
    109114
    110115        return conn;
     116
     117error:
     118        if (conn != NULL && conn->rcv_buf != NULL)
     119                free(conn->rcv_buf);
     120        if (conn != NULL && conn->snd_buf != NULL)
     121                free(conn->snd_buf);
     122        if (conn != NULL && conn->tw_timer != NULL)
     123                fibril_timer_destroy(conn->tw_timer);
     124        if (conn != NULL)
     125                free(conn);
     126
     127        return NULL;
    111128}
    112129
     
    803820                        log_msg(LVL_DEBUG, "FIN received -> Time-Wait");
    804821                        conn->cstate = st_time_wait;
    805                         /* XXX start time-wait timer */
     822                        /* Start the Time-Wait timer */
     823                        tcp_conn_tw_timer_set(conn);
    806824                        break;
    807825                case st_close_wait:
     
    811829                        break;
    812830                case st_time_wait:
    813                         /* XXX Restart the 2 MSL time-wait timeout */
     831                        /* Restart the Time-Wait timer */
     832                        tcp_conn_tw_timer_set(conn);
    814833                        break;
    815834                }
     
    912931}
    913932
     933/** Time-Wait timeout handler.
     934 *
     935 * @param arg   Connection
     936 */
     937static void tw_timeout_func(void *arg)
     938{
     939        tcp_conn_t *conn = (tcp_conn_t *) arg;
     940
     941        log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
     942        log_msg(LVL_DEBUG, " TW Timeout -> Closed");
     943
     944        tcp_conn_remove(conn);
     945        conn->cstate = st_closed;
     946}
     947
     948/** Start or restart the Time-Wait timeout.
     949 *
     950 * @param conn          Connection
     951 */
     952void tcp_conn_tw_timer_set(tcp_conn_t *conn)
     953{
     954        fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
     955            (void *)conn);
     956}
     957
    914958/** Trim segment to the receive window.
    915959 *
  • uspace/srv/net/tl/tcp/state.c

    r6e88fea r2a3214e  
    209209}
    210210
    211 /** Time-wait timeout */
    212 void tcp_to_time_wait(void)
    213 {
    214         log_msg(LVL_DEBUG, "tcp_to_time_wait()");
    215 }
    216 
    217211/**
    218212 * @}
  • uspace/srv/net/tl/tcp/state.h

    r6e88fea r2a3214e  
    5959extern void tcp_to_user(void);
    6060extern void tcp_to_retransmit(void);
    61 extern void tcp_to_time_wait(void);
    6261
    6362#endif
  • uspace/srv/net/tl/tcp/tcp_type.h

    r6e88fea r2a3214e  
    122122        tcp_tqueue_t retransmit;
    123123
     124        /** Time-Wait timeout timer */
     125        fibril_timer_t *tw_timer;
     126
    124127        /** Receive buffer */
    125128        uint8_t *rcv_buf;
Note: See TracChangeset for help on using the changeset viewer.