diff options
author | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2004-02-06 21:13:14 +0000 |
---|---|---|
committer | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2004-02-06 21:13:14 +0000 |
commit | 839b5172e6bb6c2dcb0ba0eb5ae6ae631af746ff (patch) | |
tree | f5415e24d91fdb789c9dc814dec58b3afb6e215e /zaptel.c | |
parent | 5377e38362656507d448ea811813a971f1509443 (diff) |
Clear pseudos at end of interrupt handler ONLY
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@308 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'zaptel.c')
-rwxr-xr-x | zaptel.c | 43 |
1 files changed, 42 insertions, 1 deletions
@@ -296,6 +296,10 @@ static struct zt_timer { static spinlock_t zaptimerlock = SPIN_LOCK_UNLOCKED; +static spinlock_t zapfreelock = SPIN_LOCK_UNLOCKED; + +static int zapneedfree = 0; + struct zt_zone { char name[40]; /* Informational, only */ int ringcadence[ZT_MAX_CADENCE]; @@ -1458,6 +1462,17 @@ static struct ppp_channel_ops ztppp_ops = }; #endif + +static void __zt_recalc_maxchans(void) +{ + int x; + maxchans = 0; + for (x=1;x<ZT_MAX_CHANNELS;x++) + if (chans[x]) { + maxchans = x + 1; + } +} + static void zt_chan_unreg(struct zt_chan *chan) { int x; @@ -2064,6 +2079,8 @@ static int zt_specchan_open(struct inode *inode, struct file *file, int unit, in /* Make sure we're not already open, a net device, or a slave device */ if (chans[unit]->flags & ZT_FLAG_OPEN) res = -EBUSY; + else if (chans[unit]->flags & ZT_FLAG_DEAD) + res = -EBUSY; else if (chans[unit]->flags & ZT_FLAG_NETDEV) res = -EBUSY; else if (chans[unit]->master != chans[unit]) @@ -2131,7 +2148,7 @@ static struct zt_chan *zt_alloc_pseudo(void) return pseudo; } -static void zt_free_pseudo(struct zt_chan *pseudo) +static void __zt_free_pseudo(struct zt_chan *pseudo) { if (pseudo) { zt_chan_unreg(pseudo); @@ -2139,6 +2156,18 @@ static void zt_free_pseudo(struct zt_chan *pseudo) } } +static void zt_free_pseudo(struct zt_chan *pseudo) +{ + long flags; + if (pseudo) { + /* Mark as dead for later reaping */ + pseudo->flags |= ZT_FLAG_DEAD; + spin_lock_irqsave(&zapfreelock, flags); + zapneedfree = 1; + spin_unlock_irqrestore(&zapfreelock, flags); + } +} + static int zt_open(struct inode *inode, struct file *file) { int unit = UNIT(file); @@ -5845,6 +5874,18 @@ int zt_receive(struct zt_span *span) spin_unlock_irqrestore(&chans[x]->lock, flags); } } + spin_lock_irqsave(&zapfreelock, flags); + if (zapneedfree) { + /* Free any pseudos that might need it */ + for (x=0;x<maxchans;x++) { + if (chans[x] && (chans[x]->flags & ZT_FLAG_DEAD)) { + __zt_free_pseudo(chans[x]); + } + } + } + __zt_recalc_maxchans(); + spin_unlock_irqrestore(&zapfreelock, flags); + } #endif return 0; |