1 /*
2   auxfd.c:
3 
4   Copyright (C) 1991 Barry Vercoe, John ffitch
5 
6   This file is part of Csound.
7 
8   The Csound Library is free software; you can redistribute it
9   and/or modify it under the terms of the GNU Lesser General Public
10   License as published by the Free Software Foundation; either
11   version 2.1 of the License, or (at your option) any later version.
12 
13   Csound is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU Lesser General Public License for more details.
17 
18   You should have received a copy of the GNU Lesser General Public
19   License along with Csound; if not, write to the Free Software
20   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21   02110-1301 USA
22 */
23 
24 #include "csoundCore.h"                         /*      AUXFD.C         */
25 
26 static CS_NOINLINE void auxchprint(CSOUND *, INSDS *);
27 static CS_NOINLINE void fdchprint(CSOUND *, INSDS *);
28 
29 /* allocate an auxds, or expand an old one */
30 /*    call only from init (xxxset) modules */
31 
csoundAuxAlloc(CSOUND * csound,size_t nbytes,AUXCH * auxchp)32 void csoundAuxAlloc(CSOUND *csound, size_t nbytes, AUXCH *auxchp)
33 {
34     if (auxchp->auxp != NULL) {
35       /* if allocd with same size, just clear to zero */
36       if (nbytes == (size_t)auxchp->size) {
37         memset(auxchp->auxp, 0, nbytes);
38         return;
39       }
40       else {
41         void  *tmp = auxchp->auxp;
42         /* if size change only, free the old space and re-allocate */
43         auxchp->auxp = NULL;
44         csound->Free(csound, tmp);
45       }
46     }
47     else {                                  /* else link in new auxch blk */
48       auxchp->nxtchp = csound->curip->auxchp;
49       csound->curip->auxchp = auxchp;
50     }
51     /* now alloc the space and update the internal data */
52     auxchp->size = nbytes;
53     auxchp->auxp = csound->Calloc(csound, nbytes);
54     auxchp->endp = (char*)auxchp->auxp + nbytes;
55     if (UNLIKELY(csound->oparms->odebug))
56       auxchprint(csound, csound->curip);
57 }
58 
59 
alloc_thread(void * p)60 static uintptr_t alloc_thread(void *p) {
61     AUXASYNC *pp = (AUXASYNC *) p;
62     CSOUND *csound = pp->csound;
63     AUXCH newm;
64     char *ptr;
65     if (pp->auxchp->auxp == NULL) {
66       /* Allocate new memory */
67       newm.size = pp->nbytes;
68       newm.auxp = csound->Calloc(csound, pp->nbytes);
69       newm.endp = (char*) newm.auxp + pp->nbytes;
70       ptr = (char *) newm.auxp;
71       newm  = *(pp->notify(csound, pp->userData, &newm));
72       /* check that the returned pointer is not
73          NULL and that is not the memory we have
74          just allocated in case the old memory was
75          never swapped back.
76       */
77       if (newm.auxp != NULL && newm.auxp != ptr)
78         csound->Free(csound, newm.auxp);
79     } else {
80       csoundAuxAlloc(csound,pp->nbytes,pp->auxchp);
81       pp->notify(csound, pp->userData, pp->auxchp);
82     }
83     return 0;
84 }
85 
86 
87 
88 /* Allocate an auxds asynchronously and
89    pass the newly allocated memory via a
90    callback, where it can be swapped if necessary.
91 */
csoundAuxAllocAsync(CSOUND * csound,size_t nbytes,AUXCH * auxchp,AUXASYNC * as,aux_cb cb,void * userData)92 int csoundAuxAllocAsync(CSOUND *csound, size_t nbytes, AUXCH *auxchp,
93                         AUXASYNC *as, aux_cb cb, void *userData) {
94     as->csound = csound;
95     as->nbytes = nbytes;
96     as->auxchp = auxchp;
97     as->notify = cb;
98     as->userData = userData;
99     if (UNLIKELY(csoundCreateThread(alloc_thread, as) == NULL))
100       return CSOUND_ERROR;
101     else
102       return CSOUND_SUCCESS;
103 }
104 
105 
106 /* put fdchp into chain of fd's for this instr */
107 /*      call only from init (xxxset) modules   */
108 
fdrecord(CSOUND * csound,FDCH * fdchp)109 void fdrecord(CSOUND *csound, FDCH *fdchp)
110 {
111     fdchp->nxtchp = csound->curip->fdchp;
112     csound->curip->fdchp = fdchp;
113     if (UNLIKELY(csound->oparms->odebug))
114       fdchprint(csound, csound->curip);
115 }
116 
117 /* close a file and remove from fd chain */
118 /*  call only from inits, after fdrecord */
119 
csound_fd_close(CSOUND * csound,FDCH * fdchp)120 void csound_fd_close(CSOUND *csound, FDCH *fdchp)
121 {
122     FDCH    *prvchp = NULL, *nxtchp;
123 
124     nxtchp = csound->curip->fdchp;              /* from current insds,  */
125     while (LIKELY(nxtchp != NULL)) {            /* chain through fdlocs */
126       if (UNLIKELY(nxtchp == fdchp)) {          /*   till find this one */
127         void  *fd = fdchp->fd;
128         if (LIKELY(fd)) {
129           fdchp->fd = NULL;                     /* then delete the fd   */
130           csoundFileClose(csound, fd);          /*   close the file &   */
131         }
132         if (prvchp)
133           prvchp->nxtchp = fdchp->nxtchp;       /* unlnk from fdchain   */
134         else
135           csound->curip->fdchp = fdchp->nxtchp;
136         if (UNLIKELY(csound->oparms->odebug))
137           fdchprint(csound, csound->curip);
138         return;
139       }
140       prvchp = nxtchp;
141       nxtchp = nxtchp->nxtchp;
142     }
143     fdchprint(csound, csound->curip);
144     csound->Die(csound, Str("csound_fd_close: no record of fd %p"), fdchp->fd);
145 }
146 
147 /* release all xds in instr auxp chain */
148 /*   called by insert at orcompact     */
149 
auxchfree(CSOUND * csound,INSDS * ip)150 void auxchfree(CSOUND *csound, INSDS *ip)
151 {
152     if (UNLIKELY(csound->oparms->odebug))
153       auxchprint(csound, ip);
154     while (LIKELY(ip->auxchp != NULL)) {        /* for all auxp's in chain: */
155       void  *auxp = (void*) ip->auxchp->auxp;
156       AUXCH *nxt = ip->auxchp->nxtchp;
157       memset((void*) ip->auxchp, 0, sizeof(AUXCH)); /*  delete the pntr     */
158       csound->Free(csound, auxp);                   /*  & free the space    */
159       ip->auxchp = nxt;
160     }
161     if (UNLIKELY(csound->oparms->odebug))
162       auxchprint(csound, ip);
163 }
164 
165 /* close all files in instr fd chain        */
166 /* called by insert on deact & expire       */
167 /* (also musmon on s-code, & fgens for gen01) */
168 
fdchclose(CSOUND * csound,INSDS * ip)169 void fdchclose(CSOUND *csound, INSDS *ip)
170 {
171     if (UNLIKELY(csound->oparms->odebug))
172       fdchprint(csound, ip);
173     /* for all fd's in chain: */
174     for ( ; ip->fdchp != NULL; ip->fdchp = ip->fdchp->nxtchp) {
175       void  *fd = ip->fdchp->fd;
176       if (LIKELY(fd)) {
177         ip->fdchp->fd = NULL;           /*    delete the fd     */
178         csoundFileClose(csound, fd);    /*    & close the file  */
179       }
180     }
181     if (UNLIKELY(csound->oparms->odebug))
182       fdchprint(csound, ip);
183 }
184 
185 /* print the xp chain for this insds blk */
186 
auxchprint(CSOUND * csound,INSDS * ip)187 static CS_NOINLINE void auxchprint(CSOUND *csound, INSDS *ip)
188 {
189     AUXCH *curchp;
190     char *name = csound->engineState.instrtxtp[ip->insno]->insname;
191 
192     if (name)
193       csoundMessage(csound, Str("auxlist for instr %s [%d] (%p):\n"),
194                       name, ip->insno, ip);
195     else
196       csoundMessage(csound, Str("auxlist for instr %d (%p):\n"),
197                       ip->insno, ip);
198     /* chain through auxlocs */
199     for (curchp = ip->auxchp; curchp != NULL; curchp = curchp->nxtchp)
200       csoundMessage(csound,
201                       Str("\tauxch at %p: size %zu, auxp %p, endp %p\n"),
202                       curchp, curchp->size, curchp->auxp, curchp->endp);
203 }
204 
205 /* print the fd chain for this insds blk */
206 
fdchprint(CSOUND * csound,INSDS * ip)207 static CS_NOINLINE void fdchprint(CSOUND *csound, INSDS *ip)
208 {
209     FDCH *curchp;
210     char *name = csound->engineState.instrtxtp[ip->insno]->insname;
211 
212     if (name)
213       csoundMessage(csound, Str("fdlist for instr %s [%d] (%p):"),
214                       name, ip->insno, ip);
215     else
216       csoundMessage(csound, Str("fdlist for instr %d (%p):"), ip->insno, ip);
217     /* chain through fdlocs */
218     for (curchp = ip->fdchp; curchp != NULL; curchp = curchp->nxtchp)
219       csoundMessage(csound, Str("  fd %p in %p"), curchp->fd, curchp);
220     csoundMessage(csound, "\n");
221 }
222