Index: channels/misdn/isdn_lib.c =================================================================== --- channels/misdn/isdn_lib.c (revision 212839) +++ channels/misdn/isdn_lib.c (working copy) @@ -516,6 +516,7 @@ channel--; + pthread_mutex_lock(&stack->st_lock); if (dec) { for (i = bnums; i >=0; i--) { if (i != 15 && (channel < 0 || i == channel)) { /* skip E1 D channel ;) and work with chan preselection */ @@ -539,6 +540,7 @@ } if (!chan) { + pthread_mutex_unlock(&stack->st_lock); cb_log (1, stack->port, " !! NO FREE CHAN IN STACK\n"); dump_chan_list(stack); bc->out_cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION; @@ -546,10 +548,12 @@ } if (set_chan_in_stack(stack, chan)<0) { + pthread_mutex_unlock(&stack->st_lock); cb_log (0, stack->port, "Channel Already in use:%d\n", chan); bc->out_cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL; return -1; } + pthread_mutex_unlock(&stack->st_lock); bc->channel=chan; return 0; @@ -795,9 +799,9 @@ for (i=0; i<=stack->b_num; i++) { if (global_state == MISDN_INITIALIZED) { cb_event(EVENT_CLEANUP, &stack->bc[i], NULL); - empty_chan_in_stack(stack,i+1); empty_bc(&stack->bc[i]); clean_up_bc(&stack->bc[i]); + empty_chan_in_stack(stack, i + 1); stack->bc[i].in_use = 0; } @@ -1260,6 +1264,8 @@ msg_queue_init(&stack->downqueue); msg_queue_init(&stack->upqueue); + + pthread_mutex_init(&stack->st_lock, NULL); /* query port's requirements */ ret = mISDN_get_stack_info(midev, port, buff, sizeof(buff)); @@ -1434,6 +1440,8 @@ if (stack->upper_id) mISDN_write_frame(stack->midev, buf, stack->upper_id, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC); + + pthread_mutex_destroy(&stack->st_lock); } @@ -1479,8 +1487,11 @@ static struct misdn_bchannel *find_bc_by_masked_l3id(struct misdn_stack *stack, unsigned long l3id, unsigned long mask) { int i; - for (i=0; i<=stack->b_num; i++) { - if ( (stack->bc[i].l3_id & mask) == (l3id & mask)) return &stack->bc[i] ; + + for (i = 0; i <= stack->b_num; i++) { + if (stack->bc[i].in_use && (stack->bc[i].l3_id & mask) == (l3id & mask)) { + return &stack->bc[i]; + } } return stack_holder_find(stack,l3id); } @@ -1489,8 +1500,11 @@ struct misdn_bchannel *find_bc_by_l3id(struct misdn_stack *stack, unsigned long l3id) { int i; - for (i=0; i<=stack->b_num; i++) { - if (stack->bc[i].l3_id == l3id) return &stack->bc[i] ; + + for (i = 0; i <= stack->b_num; i++) { + if (stack->bc[i].in_use && stack->bc[i].l3_id == l3id) { + return &stack->bc[i]; + } } return stack_holder_find(stack,l3id); } @@ -1500,11 +1514,11 @@ struct misdn_stack *stack; int i; - for (stack=glob_mgr->stack_list; - stack; - stack=stack->next) { - for (i=0; i<=stack->b_num; i++) { - if ( (stack->bc[i].addr&STACK_ID_MASK)==(addr&STACK_ID_MASK) || stack->bc[i].layer_id== addr ) { + for (stack = glob_mgr->stack_list; stack; stack = stack->next) { + for (i = 0; i <= stack->b_num; i++) { + if (stack->bc[i].in_use + && ((stack->bc[i].addr & STACK_ID_MASK) == (addr & STACK_ID_MASK) + || stack->bc[i].layer_id == addr)) { return &stack->bc[i]; } } @@ -1518,11 +1532,9 @@ struct misdn_stack *stack; int i; - for (stack=glob_mgr->stack_list; - stack; - stack=stack->next) { - for (i=0; i<=stack->b_num; i++) { - if ( stack->bc[i].conf_id==confid ) { + for (stack = glob_mgr->stack_list; stack; stack = stack->next) { + for (i = 0; i <= stack->b_num; i++) { + if (stack->bc[i].in_use && stack->bc[i].conf_id == confid) { return &stack->bc[i]; } } @@ -1536,10 +1548,12 @@ struct misdn_stack *stack = find_stack_by_port(port); int i; - if (!stack) return NULL; + if (!stack) { + return NULL; + } - for (i=0; i<=stack->b_num; i++) { - if ( stack->bc[i].channel== channel ) { + for (i = 0; i <= stack->b_num; i++) { + if (stack->bc[i].in_use && stack->bc[i].channel == channel) { return &stack->bc[i]; } } @@ -1606,7 +1620,9 @@ if (!bc->channel) cb_log(0, stack->port, "Any Channel Requested, but we have no more!!\n"); else - cb_log(0, stack->port, "Requested Channel Already in Use releasing this call with cause 34!!!!\n"); + cb_log(0, stack->port, + "Requested Channel Already in Use releasing this call with cause %d!!!!\n", + bc->out_cause); /* when the channel is already in use, we can't * simply clear it, we need to make sure that @@ -1717,6 +1733,7 @@ /* Empties bc if it's reserved (no SETUP out yet) */ void misdn_lib_release(struct misdn_bchannel *bc) { + int channel; struct misdn_stack *stack=get_stack_by_bc(bc); if (!stack) { @@ -1724,11 +1741,12 @@ return; } - if (bc->channel>0) - empty_chan_in_stack(stack,bc->channel); - + channel = bc->channel; empty_bc(bc); clean_up_bc(bc); + if (channel > 0) { + empty_chan_in_stack(stack, channel); + } bc->in_use=0; } @@ -2774,22 +2792,19 @@ bc->cause=tmpcause; bc->out_cause=tmp_out_cause; clean_up_bc(bc); + bc->in_use = 0; if (tmpcause == AST_CAUSE_REQUESTED_CHAN_UNAVAIL) { - cb_log(0,stack->port,"**** Received CAUSE:%d, so not cleaning up channel %d\n", AST_CAUSE_REQUESTED_CHAN_UNAVAIL, channel); - cb_log(0,stack->port,"**** This channel is now no longer available,\nplease try to restart it with 'misdn send restart '\n"); - set_chan_in_stack(stack, channel); - bc->channel=channel; + cb_log(0, stack->port, "**** Received CAUSE:%d, restarting channel %d\n", AST_CAUSE_REQUESTED_CHAN_UNAVAIL, channel); misdn_lib_send_restart(stack->port, channel); - } else { - if (channel>0) - empty_chan_in_stack(stack, channel); } - bc->in_use=0; + if (channel > 0) { + empty_chan_in_stack(stack, channel); + } } if (event == EVENT_RESTART) { - cb_log(0, stack->port, "**** Received RESTART_ACK channel:%d\n", bc->restart_channel); + cb_log(0, stack->port, "**** Received RESTART channel:%d\n", bc->restart_channel); empty_chan_in_stack(stack, bc->restart_channel); } @@ -3171,11 +3186,12 @@ struct misdn_stack *stack; int i; - for (stack=glob_mgr->stack_list; - stack; - stack=stack->next) { - for (i=0; i<=stack->b_num; i++) - if (stack->bc[i].pid == pid) return &stack->bc[i]; + for (stack = glob_mgr->stack_list; stack; stack = stack->next) { + for (i = 0; i <= stack->b_num; i++) { + if (stack->bc[i].in_use && stack->bc[i].pid == pid) { + return &stack->bc[i]; + } + } } return NULL; @@ -3205,7 +3221,6 @@ { bc->channel = channel; bc->channel_preselected = channel?1:0; - bc->in_use = 1; bc->need_disconnect=1; bc->need_release=1; bc->need_release_complete=1; @@ -3219,6 +3234,8 @@ bc->b_stid=0; bc->layer_id=0; #endif + + bc->in_use = 1; } struct misdn_bchannel* misdn_lib_get_free_bc(int port, int channel, int inout, int dec) @@ -3231,8 +3248,6 @@ return NULL; } - usleep(1000); - for (stack=glob_mgr->stack_list; stack; stack=stack->next) { if (stack->port == port) { @@ -3243,21 +3258,25 @@ return NULL; } + pthread_mutex_lock(&stack->st_lock); if (channel > 0) { if (channel <= stack->b_num) { for (i = 0; i < stack->b_num; i++) { if ( stack->bc[i].channel == channel) { if (test_inuse(&stack->bc[i])) { + pthread_mutex_unlock(&stack->st_lock); cb_log(0,port,"Requested channel:%d on port:%d is already in use\n",channel, port); return NULL; } else { prepare_bc(&stack->bc[i], channel); + pthread_mutex_unlock(&stack->st_lock); return &stack->bc[i]; } } } } else { + pthread_mutex_unlock(&stack->st_lock); cb_log(0,port,"Requested channel:%d is out of bounds on port:%d\n",channel, port); return NULL; } @@ -3274,6 +3293,7 @@ prepare_bc(&stack->bc[i], channel); stack->bc[i].dec=1; + pthread_mutex_unlock(&stack->st_lock); return &stack->bc[i]; } } @@ -3285,10 +3305,12 @@ stack->bc[i].cw=1; prepare_bc(&stack->bc[i], channel); + pthread_mutex_unlock(&stack->st_lock); return &stack->bc[i]; } } } + pthread_mutex_unlock(&stack->st_lock); cb_log(1,port,"There is no free channel on port (%d)\n",port); return NULL; @@ -3867,7 +3889,7 @@ /* clean up chan in stack, to be sure we don't think it's * in use anymore */ for (cnt=0; cnt<=stack->b_num; cnt++) { - if (stack->bc[cnt].channel == channel) { + if (stack->bc[cnt].in_use && stack->bc[cnt].channel == channel) { empty_bc(&stack->bc[cnt]); clean_up_bc(&stack->bc[cnt]); stack->bc[cnt].in_use=0; Index: channels/misdn/isdn_lib_intern.h =================================================================== --- channels/misdn/isdn_lib_intern.h (revision 212839) +++ channels/misdn/isdn_lib_intern.h (working copy) @@ -58,6 +58,9 @@ manager_t mgr; pthread_mutex_t nstlock; + /*! \brief Stack struct critical section lock. */ + pthread_mutex_t st_lock; + /*! \brief D Channel mISDN driver stack ID (Parent stack ID) */ int d_stid; @@ -123,7 +126,7 @@ /*! \brief Array of B channels in use (a[0] = B1). TRUE if B channel in use */ int channels[MAX_BCHANS + 1]; - /*! \brief List of holded channels */ + /*! \brief List of held channels */ struct misdn_bchannel *holding; /*! \brief Next stack in the list of stacks */