Adding new commiter to ODU-High repo
[o-du/l2.git] / src / mt / ss_strm.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18 \f
19 /********************************************************************20**
20
21      Name:     System Services -- STREAMS
22
23      Type:     C source file
24
25      Desc:     Implementation of STREAMS messaging functions.
26
27      File:     ss_strm.c
28
29 *********************************************************************21*/
30
31 \f  
32 /* header include files (.h) */
33
34 #include "envopt.h"        /* environment options */
35 #include "envdep.h"        /* environment dependent */
36 #include "envind.h"        /* environment independent */
37   
38 #include "gen.h"           /* general layer */
39 #include "ssi.h"           /* system services */
40
41 #include "ss_err.h"        /* errors */
42 #include "ss_dep.h"        /* implementation-specific */
43 #include "ss_queue.h"      /* queues */
44 #include "ss_strm.h"       /* STREAMS */
45 #include "ss_msg.h"        /* messaging */
46 #include "ss_mem.h"        /* memory management interface */
47 #include "ss_gen.h"        /* general */
48 #include "cm_mem.h"        /* memory management */
49
50
51
52 /* header/extern include files (.x) */
53
54 #include "gen.x"           /* general layer */
55 #include "ssi.x"           /* system services */
56
57
58 #include "ss_dep.x"        /* implementation-specific */
59 #include "ss_queue.x"      /* queues */
60 #include "ss_task.x"       /* tasking */
61 #include "ss_timer.x"      /* timers */
62 #include "ss_strm.x"       /* STREAMS */
63 #include "ss_msg.x"        /* messaging */
64 #include "ss_mem.x"        /* memory management interface */
65 #include "ss_drvr.x"       /* driver tasks */
66 #ifdef SS_LOCKLESS_MEMORY
67 #include "cm_llist.x"
68 #include "cm_hash.x"
69 #include "cm_mem_wl.x"        /* common memory manager */
70 #else
71 #include "cm_mem.x"        /* common memory manager */
72 #endif /* SS_LOCKLESS_MEMORY */
73 #include "ss_gen.x"        /* general */
74
75
76 \f
77 /* private variable declarations */
78
79 static struct
80 {
81    Region mdRegion;     /* region for message and data blocks */
82    Region datRegion;    /* region for data buffers */
83 } strmCfg;
84
85
86
87 \f
88 /*
89 *     Interface functions (System Services--non-STREAMS interface)
90 */
91  
92 \f
93 /*
94 *
95 *       Fun:   ssStrmCfg
96 *
97 *       Desc:  Configures the STREAMS system.
98 *
99 *       Ret:   ROK      - ok
100 *
101 *       Notes:
102 *
103 *       File:  ss_strm.c
104 *
105 */
106 S16 ssStrmCfg
107 (
108 Region mdRegId,                 /* region for message and data blocks */
109 Region datRegId                 /* region for data buffers */
110 )
111 {
112
113    strmCfg.mdRegion = mdRegId;
114    strmCfg.datRegion = datRegId;
115
116
117    return ROK;
118 }
119
120 \f
121 /*
122 *     STREAMS interface functions
123 *
124 *       All these assume that ssStrmCfg() has been called first, with
125 *       valid parameters.
126 */
127  
128 \f
129 /*
130 *
131 *       Fun:   ssAdjMsg
132 *
133 *       Desc:  Trim abs(len) bytes from a message. If len is less than
134 *              0, trim from the tail, otherwise from the head. Operates
135 *              only on blocks of the same type. Does not remove emptied
136 *              message blocks.
137 *
138 *
139 *       Ret:   1        - ok
140 *              0        - failure
141 *
142 *       Notes:
143 *
144 *       File:  ss_strm.c
145 *
146 */
147 S32 ssAdjMsg
148 (
149 SsMblk *mp,                     /* message */
150 S32 len                         /* bytes to remove */
151 )
152 {
153    S32 n;                       /* counter */
154    S32 size;                    /* size of mblks of same type as head/tail */
155    uint8_t type;                     /* message type */
156    SsMblk *bp;                  /* mblk for iteration */
157    SsMblk *first;               /* first mblk to be adjusted */
158
159 #if (ERRCLASS & ERRCLS_INT_PAR)
160    if (mp == NULLP)
161    {
162       SSLOGERROR(ERRCLS_INT_PAR, ESS325, ERRZERO, "Null pointer");
163       return (0);
164    }
165 #endif
166
167
168    if (len == 0)                /* nothing to do */
169    {
170       return (1);
171    }
172
173
174    if (len > 0)                 /* trim from the head */
175    {
176       /* figure out the size of all blocks of the same type as the head */
177       bp = mp;
178       size = 0;
179       type = bp->b_datap->db_type;
180       while (bp  &&  bp->b_datap->db_type == type)
181       {
182          n = bp->b_wptr - bp->b_rptr;
183          if (n > 0)
184          {
185             size += n;
186          }
187
188          bp = bp->b_cont;
189       }
190
191
192       /* if we can't trim len bytes, fail */
193       if (len > size)
194       {
195          return (0);
196       }
197
198
199       /* do the trimming */
200       bp = mp;
201       for (; ;)
202       {
203          n = bp->b_wptr - bp->b_rptr;
204
205          if (n >= len)
206          {
207             bp->b_rptr += len;
208             break;
209          }
210          else if (n > 0)
211          {
212             bp->b_rptr += len;
213             len -= n;
214          }
215
216          bp = bp->b_cont;
217       }
218    }
219    else                         /* trim from the tail */
220    {
221       /* figure out the size of all blocks of the same type as the tail */
222       bp = mp;
223       first = bp;
224       size = 0;
225       type = bp->b_datap->db_type;
226       while (bp)
227       {
228          if (bp->b_datap->db_type == type)
229          {
230             n = bp->b_wptr - bp->b_rptr;
231             if (n > 0)
232             {
233                size += n;
234             }
235          }
236          else
237          {
238             type = bp->b_datap->db_type;
239             first = bp;
240             size = 0;
241          }
242
243          bp = bp->b_cont;
244       }
245
246
247       /* if we can't trim len bytes, fail */
248       size += len;
249       if (size < 0)
250       {
251          return (0);
252       }
253
254
255       /* do the trimming */
256       while (first)
257       {
258          n = first->b_wptr - first->b_rptr;
259
260          if (size <= 0)
261          {
262             first->b_rptr = first->b_wptr;
263          }
264          else if (n > 0)
265          {
266             if (n > size)
267             {
268                first->b_wptr = first->b_rptr + size;
269             }
270
271             size -= n;
272          }
273
274          first = first->b_cont;
275       }
276    }
277
278
279    return (1);
280 } /* ssAdjMsg */
281
282 \f
283 /*
284 *
285 *       Fun:   ssAllocB
286 *
287 *       Desc:  Returns a pointer to a message block of type M_DATA
288 *              in which the data buffer is of at least the specified
289 *              size.
290 *
291 *
292 *       Ret:   non-NULL - success
293 *              NULL     - failure
294 *
295 *       Notes: The parameter pri is unused.
296 *
297 *       File:  ss_strm.c
298 *
299 */
300 SsMblk *ssAllocB
301 (
302 S32 size,                       /* required size */
303 uint32_t pri                         /* message priority */
304 )
305 {
306    SsMblk *bp;                  /* mblk for iteration */
307    Data *dat;                   /* pointer to data buffer */
308    Size m;                      /* temporary */
309    Size n;                      /* temporary */
310    S16 r;                       /* return value */
311
312
313 #ifdef T2K_MEM_LEAK_DBG
314    char* file = __FILE__;
315    uint32_t line = __LINE__;
316 #endif
317
318    UNUSED(pri);
319
320
321    /* allocate a single block for the mblock and the dblock */
322    m = (sizeof(SsMblk) + sizeof(SsDblk));
323 /* ss001.301: additions */
324 #ifdef SS_HISTOGRAM_SUPPORT
325    r = SAlloc(strmCfg.mdRegion, &m, 0, (Data **)&bp, __LINE__, (uint8_t*)__FILE__, ENTNC);
326 #else
327    r = SAlloc(strmCfg.mdRegion, &m, 0, (Data **)&bp);
328 #endif /* SS_HISTOGRAM_SUPPORT */
329    if (r != ROK)
330    {
331 #if (ERRCLASS & ERRCLS_ADD_RES)
332       SSLOGERROR(ERRCLS_ADD_RES, ESS326, (ErrVal) r, "SAlloc() failed");
333 #endif
334
335       return (NULLP);
336    }
337
338
339    /* allocate space for the data block */
340    if (size > 0)
341    {
342       n = size;
343 /* ss001.301: additions */
344 #ifdef SS_HISTOGRAM_SUPPORT
345       r = SAlloc(strmCfg.datRegion, &n, 0, &dat, __LINE__, (uint8_t*)__FILE__, ENTNC);
346 #else
347       r = SAlloc(strmCfg.datRegion, &n, 0, &dat);
348 #endif /* SS_HISTOGRAM_SUPPORT */
349       if (r != ROK)
350       {
351 #if (ERRCLASS & ERRCLS_ADD_RES)
352          SSLOGERROR(ERRCLS_ADD_RES, ESS327, (ErrVal) r, "SAlloc() failed");
353 #endif
354
355 /* ss001.301: additions */
356 #ifdef SS_HISTOGRAM_SUPPORT
357          SFree(strmCfg.mdRegion, (Data *)bp, m, __LINE__, (uint8_t*)__FILE__, ENTNC);
358 #else
359          SFree(strmCfg.mdRegion, (Data *)bp, m);
360 #endif /* SS_HISTOGRAM_SUPPORT */
361          return (NULLP);
362       }
363    }
364    /* we _can_ allocate a message with an empty data block */
365    else
366    {
367       dat = NULLP;
368    }
369
370    /* generic set-up-message function */
371    SS_STRM_INITB(bp, (SsDblk *)(((uint8_t *)bp) + sizeof(SsMblk)), dat, size, NULLP);
372
373
374    return (bp);
375 } /* ssAllocB */
376
377 \f
378 /*
379 *
380 *       Fun:   ssCopyB
381 *
382 *       Desc:  Copies the contents of the specified message block
383 *              into a newly-allocated message block of at least
384 *              the same size. Calls ssAllocB().
385 *
386 *       Ret:   non-NULL - ok
387 *              NULL     - failure
388 *
389 *       Notes:
390 *
391 *       File:  ss_strm.c
392 *
393 */
394 SsMblk *ssCopyB
395 (
396 SsMblk *mp                      /* message block */
397 )
398 {
399    SsMblk *bp;                  /* mblk for iteration */
400    uint8_t *ptr;                     /* pointer to data */
401    uint32_t size;                    /* size of data content */
402
403
404 #if (ERRCLASS & ERRCLS_INT_PAR)
405    if (mp == NULLP)
406    {
407       SSLOGERROR(ERRCLS_INT_PAR, ESS328, ERRZERO, "Null pointer");
408       return (NULLP);
409    }
410 #endif
411
412
413    /* allocate another message */
414    bp = ssAllocB((mp->b_datap->db_lim - mp->b_datap->db_base), 0);
415    if (bp == NULLP)
416    {
417 #if (ERRCLASS & ERRCLS_ADD_RES)
418       SSLOGERROR(ERRCLS_ADD_RES, ESS329, ERRZERO, "ssAllocB() failed");
419 #endif
420
421       return (NULLP);
422    }
423
424
425    /* copy the contents, if any */
426    size = (mp->b_wptr - mp->b_rptr);
427    if (size > 0)
428    {
429       ptr = mp->b_rptr;
430       while (ptr != mp->b_wptr)
431       {
432          *bp->b_wptr++ = *ptr++;
433       }
434    }
435
436
437    return (bp);
438 } /* ssCopyB */
439
440 \f
441 /*
442 *
443 *       Fun:   ssCopyMsg
444 *
445 *       Desc:  Uses ssCopyB to copy the message blocks contained in
446 *              the specified message to newly allocated blocks and
447 *              links those blocks into a new message.
448 *
449 *       Ret:   non-NULL - ok
450 *              NULL     - failure
451 *
452 *       Notes:
453 *
454 *       File:  ss_strm.c
455 *
456 */
457 SsMblk *ssCopyMsg
458 (
459 SsMblk *mp                      /* message block */
460 )
461 {
462    SsMblk *first;               /* first mblk in message */
463    SsMblk *bp;                  /* mblk for iteration */
464
465 #if (ERRCLASS & ERRCLS_INT_PAR)
466    if (mp == NULLP)
467    {
468       SSLOGERROR(ERRCLS_INT_PAR, ESS330, ERRZERO, "Null pointer");
469       return (NULLP);
470    }
471 #endif
472
473
474    /* copy the first mblock */
475    first = bp = ssCopyB(mp);
476    if (bp == NULLP)
477    {
478 #if (ERRCLASS & ERRCLS_ADD_RES)
479       SSLOGERROR(ERRCLS_ADD_RES, ESS331, ERRZERO, "ssCopyB() failed");
480 #endif
481
482       return (NULLP);
483    }
484
485
486    /* copy all the rest, linking the new ones at the same time */
487    while (mp->b_cont)
488    {
489       mp = mp->b_cont;
490
491       bp->b_cont = ssCopyB(mp);
492
493       /* if any copy fails, free whatever exists of the new message */
494       if (bp->b_cont == NULLP)
495       {
496 #if (ERRCLASS & ERRCLS_ADD_RES)
497          SSLOGERROR(ERRCLS_ADD_RES, ESS332, ERRZERO, "ssCopyB() failed");
498 #endif
499
500          ssFreeMsg(first);
501          return (NULLP);
502       }
503
504       bp = bp->b_cont;
505    }
506
507
508    return (first);
509 } /* ssCopyMsg */
510
511 \f
512 /*
513 *
514 *       Fun:   ssDupB
515 *
516 *       Desc:  Duplicates the specified message block, copying it
517 *              into a newly-allocated message block. Increments
518 *              the reference count of the data block that is pointed
519 *              at by the original message block descriptor.
520 *
521 *       Ret:   non-NULL - ok
522 *              NULL     - failure
523 *
524 *       Notes:
525 *
526 *       File:  ss_strm.c
527 *
528 */
529 SsMblk *ssDupB
530 (
531 SsMblk *mp                      /* message block */
532 )
533 {
534    SsMblk *bp;                  /* mblk for iteration */
535    /* ss028.103 - Addition of lock for mBuf reference count */
536
537 #if (ERRCLASS & ERRCLS_INT_PAR)
538    if (mp == NULLP)
539    {
540       SSLOGERROR(ERRCLS_INT_PAR, ESS333, ERRZERO, "Null pointer");
541       return (NULLP);
542    }
543 #endif
544
545
546    /* allocate a message with no data buffer */
547    bp = ssAllocB(0, 0);
548    if (bp == NULLP)
549    {
550 #if (ERRCLASS & ERRCLS_ADD_RES)
551       SSLOGERROR(ERRCLS_ADD_RES, ESS334, ERRZERO, "ssAllocB() failed");
552 #endif
553
554       return (NULLP);
555    }
556
557
558    /*  make the new message block identical to the one to be dup'ed.
559     *  notice that an mblk/dblk pair is allocated but only the mblk
560     *  is used,, this is for optimum performance in the average case.
561     */
562
563
564
565  /* ss002.13: addition */
566
567
568  /* ss003.13: addition */
569    SMemCpy( (Void *)bp, (Void *)mp, (size_t)sizeof(SsMblk));
570
571
572    /* ss028.103 - Addition of lock for mBuf reference count */
573         /* ss006.301 - use the mBufRefLock for the DFLT_REGION */
574 #ifndef SS_DBUF_REFLOCK_DISABLE
575    if(SLock(&mp->b_datap->dBufLock) != ROK)
576    {
577       SSLOGERROR(ERRCLS_DEBUG, ESS335, ERRZERO,
578                      "Could not lock the mBuf Ref Lock");
579       return (NULLP);
580    }
581 #endif
582
583    /* increment the reference count of the dblock */
584    mp->b_datap->db_ref++;
585    mp->b_datap->shared = TRUE;
586
587         /* ss006.301 - use the mBufRefLock for the DFLT_REGION */
588 #ifndef SS_DBUF_REFLOCK_DISABLE
589    if ( SUnlock(&mp->b_datap->dBufLock) != ROK)
590    {
591 #if (ERRCLASS & ERRCLS_DEBUG)
592       SSLOGERROR(ERRCLS_DEBUG, ESS336, ERRZERO,
593                       "Could not give the Semaphore");
594       return (NULLP);
595 #endif
596    }
597 #endif
598
599    return (bp);
600 } /* ssDupB */
601
602 \f
603 /*
604 *
605 *       Fun:   ssDupMsg
606 *
607 *       Desc:  Calls ssDupB to duplicate the specified message by
608 *              copying all message block descriptors and then linking
609 *              the new message blocks together to form a new message.
610 *
611 *       Ret:   non-NULL - ok
612 *              NULL     - failure
613 *
614 *       Notes:
615 *
616 *       File:  ss_strm.c
617 *
618 */
619 SsMblk *ssDupMsg
620 (
621 SsMblk *mp                      /* message block */
622 )
623 {
624    SsMblk *first;               /* first mblk in message */
625    SsMblk *bp;                  /* mblk for iteration */
626
627    /* dup the first mblock */
628    first = bp = ssDupB(mp);
629    if (bp == NULLP)
630    {
631 #if (ERRCLASS & ERRCLS_ADD_RES)
632       SSLOGERROR(ERRCLS_ADD_RES, ESS337, ERRZERO, "ssDupB() failed");
633 #endif
634
635       return (NULLP);
636    }
637
638
639    /* dup all the rest, linking the new ones at the same time */
640    while (mp->b_cont)
641    {
642       mp = mp->b_cont;
643
644       bp->b_cont = ssDupB(mp);
645
646       /* if any dup fails, free whatever exists of the new message */
647       if (bp->b_cont == NULLP)
648       {
649 #if (ERRCLASS & ERRCLS_ADD_RES)
650          SSLOGERROR(ERRCLS_ADD_RES, ESS338, ERRZERO, "ssDupB() failed");
651 #endif
652
653          ssFreeMsg(first);
654          return (NULLP);
655       }
656
657       bp = bp->b_cont;
658    }
659
660
661    return (first);
662 } /* ssDupMsg */
663
664 \f
665 /*
666 *
667 *       Fun:   ssESBAlloc
668 *
669 *       Desc:  Allocates message and data blocks that point directly
670 *              at a client-supplied buffer.
671 *
672 *       Ret:   non-NULL - ok
673 *              NULL     - failure
674 *
675 *       Notes:
676 *
677 *       File:  ss_strm.c
678 *
679 */
680 SsMblk *ssESBAlloc
681 (
682 uint8_t *base,                       /* client supplied data buffer */
683 S32 size,                       /* size of data buffer */
684 S32 pri,                        /* message priority */
685 SsFrtn *fr_rtn                  /* free routine */
686 )
687 {
688    SsMblk *bp;                  /* mblk for iteration */
689    Size m;                      /* mblk + dblk */
690    S16 r;                       /* return value */
691
692    UNUSED(pri);
693
694
695 #if (ERRCLASS & ERRCLS_INT_PAR)
696    if (base == NULLP  ||  fr_rtn == NULLP)
697    {
698       SSLOGERROR(ERRCLS_INT_PAR, ESS339, ERRZERO, "Null pointer");
699       return (NULLP);
700    }
701 #endif
702
703
704    /* allocate space for an mblock and a dblock */
705    m = (sizeof(SsMblk) + sizeof(SsDblk));
706 /* ss001.301: additions */
707 #ifdef SS_HISTOGRAM_SUPPORT
708    r = SAlloc(strmCfg.mdRegion, &m, 0, (Data **)&bp, __LINE__, (uint8_t*)__FILE__, ENTNC);
709 #else
710 #ifdef T2K_MEM_LEAK_DBG
711    char* file = __FILE__;
712    uint32_t line = __LINE__;
713 #endif
714    r = SAlloc(strmCfg.mdRegion, &m, 0, (Data **)&bp);
715 #endif /* SS_HISTOGRAM_SUPPORT */
716    if (r != ROK)
717    {
718 #if (ERRCLASS & ERRCLS_ADD_RES)
719       SSLOGERROR(ERRCLS_ADD_RES, ESS340, (ErrVal) r, "SAlloc() failed");
720 #endif
721
722       return (NULLP);
723    }
724
725
726    /* use the generic set-up-message function to initialize everything */
727    SS_STRM_INITB(bp, (SsDblk *)(((uint8_t *)bp) + sizeof(SsMblk)),
728                   base, size, fr_rtn);
729
730
731    return (bp);
732 } /* ssESBAlloc */
733
734 \f
735 /*
736 *
737 *       Fun:   ssFreeB
738 *
739 *       Desc:  Deallocates the specified message block descriptor
740 *              and frees the corresponding data block if the
741 *              reference count is equal to 1. If not, the reference
742 *              count is decremented.
743 *
744 *       Ret:   Void
745 *
746 *       Notes:
747 *
748 *       File:  ss_strm.c
749 *
750 */
751 Void ssFreeB
752 (
753 SsMblk *mp                      /* message block */
754 )
755 {
756    SsMblk *bp;                  /* mblk for iteration */
757    Size size;                   /* mblk + dblk */
758    /* ss028.103 - Addition of lock for mBuf reference count */
759
760 #ifdef T2K_MEM_LEAK_DBG
761    char* file = __FILE__;
762    uint32_t line = __LINE__;
763 #endif
764
765 #if (ERRCLASS & ERRCLS_INT_PAR)
766    if (mp == NULLP)
767    {
768       SSLOGERROR(ERRCLS_INT_PAR, ESS341, ERRZERO, "Null pointer");
769       return;
770    }
771 #endif
772
773
774    size = sizeof(SsMblk) + sizeof(SsDblk);
775
776
777    /*  this mblock has already been freed, and still exists only
778     *  because there is a reference to its dblock. it will be
779     *  freed when the referring mblock is freed.
780     */
781
782    if (mp->b_datap == NULLP)
783    {
784       return;
785    }
786
787
788    /* ?? this should never happen ?? */
789    if (mp->b_datap->db_ref == 0)
790    {
791 #if (ERRCLASS & ERRCLS_DEBUG)
792       SSLOGERROR(ERRCLS_DEBUG, ESS342, ERRZERO,
793                   "Zero reference count in ssFreeB; logic failure");
794 #endif
795
796 /* ss001.301: additions */
797 #ifdef SS_HISTOGRAM_SUPPORT
798       SFree(strmCfg.mdRegion, (Data *)mp, size, __LINE__, (uint8_t*)__FILE__, ENTNC);
799 #else
800 #ifdef T2K_MEM_LEAK_DBG
801       SFree(strmCfg.mdRegion, (Data *)mp, size);
802 #else
803       SFree(strmCfg.mdRegion, (Data *)mp, size);
804 #endif
805 #endif /* SS_HISTOGRAM_SUPPORT */
806       return;
807    }
808
809    /* ss028.103 - Addition of lock for mBuf reference count */
810         /* ss006.301 - use the mBufRefLock for the DFLT_REGION */
811 #ifndef SS_DBUF_REFLOCK_DISABLE
812    if(SLock(&mp->b_datap->dBufLock) != ROK)
813    {
814       SSLOGERROR(ERRCLS_DEBUG, ESS343, ERRZERO,
815                      "Could not lock the mBuf Ref Lock");
816       return;
817    }
818 #endif
819
820    /* decrement reference count of the dblock */
821    mp->b_datap->db_ref--;
822
823         /* ss006.301 - use the mBufRefLock for the DFLT_REGION */
824 #ifndef SS_DBUF_REFLOCK_DISABLE
825    if ( SUnlock(&mp->b_datap->dBufLock) != ROK)
826    {
827 #if (ERRCLASS & ERRCLS_DEBUG)
828       SSLOGERROR(ERRCLS_DEBUG, ESS344, ERRZERO,
829                       "Could not give the Semaphore");
830       return;
831 #endif
832    }
833 #endif
834
835    /*  if we have no more references to this dblock, we can free
836     *  the data buffer and the header.
837     */
838
839    if (mp->b_datap->db_ref == 0)
840    {
841       /*  if there is a free routine, we call it for the data buffer;
842        *  otherwise, we've allocated the data buffer and so we free it.
843        */
844 #ifndef SS_DBUF_REFLOCK_DISABLE
845        SDestroyLock(&mp->b_datap->dBufLock);
846 #endif
847 /* ss008.301 */
848 #ifdef SS_DBLK_FREE_RTN 
849       if (mp->b_datap->db_frtnp)
850       {
851          (*(mp->b_datap->db_frtnp->free_func))(mp->b_datap->db_frtnp->free_arg);
852       }
853       else
854 #endif      
855       if (mp->b_datap->db_base != NULLP)
856       {
857 /* ss001.301: additions */
858 #ifdef SS_HISTOGRAM_SUPPORT
859          SFree(strmCfg.datRegion, mp->b_datap->db_base,
860                   (Size)(mp->b_datap->db_lim - mp->b_datap->db_base), 
861                                                 __LINE__, (uint8_t*)__FILE__, ENTNC);
862 #else
863          SFree(strmCfg.datRegion, mp->b_datap->db_base,
864                   (Size)(mp->b_datap->db_lim - mp->b_datap->db_base));
865 #endif /* SS_HISTOGRAM_SUPPORT */
866       }
867
868
869       /*  if the dblock is in this header, we free this header
870        *  and we're done. if the dblock is in another header,
871        *  we have to free that header too.
872        */
873
874       if (mp->b_datap != ((SsDblk *)(mp + sizeof(SsMblk))))
875       {
876          bp = (SsMblk *)(mp->b_datap - sizeof (SsMblk));
877 /* ss001.301: additions */
878 #ifdef SS_HISTOGRAM_SUPPORT
879          SFree(strmCfg.mdRegion, (Data *)bp, size, __LINE__, (uint8_t*)__FILE__, ENTNC);
880 #else
881          SFree(strmCfg.mdRegion, (Data *)bp, size);
882 #endif /* SS_HISTOGRAM_SUPPORT */
883       }
884
885 /* ss001.301: additions */
886 #ifdef SS_HISTOGRAM_SUPPORT
887       SFree(strmCfg.mdRegion, (Data *)mp, size, __LINE__, (uint8_t*)__FILE__, ENTNC);
888 #else
889       SFree(strmCfg.mdRegion, (Data *)mp, size);
890 #endif /* SS_HISTOGRAM_SUPPORT */
891    }
892    else
893    {
894       /*  reference count is non-zero; if it is this header's
895        *  dblock, we don't free the header, we just mark the
896        *  dblock pointer empty so we know about it. if it is
897        *  another header's dblock, we can free this header.
898        */
899
900       if (mp->b_datap == (SsDblk *)(mp + sizeof(SsMblk)))
901       {
902          mp->b_datap = NULLP;
903       }
904       else
905       {
906 /* ss001.301: additions */
907 #ifdef SS_HISTOGRAM_SUPPORT
908          SFree(strmCfg.mdRegion, (Data *)mp, size, __LINE__, (uint8_t*)__FILE__, ENTNC);
909 #else
910          SFree(strmCfg.mdRegion, (Data *)mp, size);
911 #endif /* SS_HISTOGRAM_SUPPORT */
912       }
913    }
914
915    return;
916 } /* ssFreeB */
917
918 \f
919 /*
920 *
921 *       Fun:   ssFreeMsg
922 *
923 *       Desc:  Calls ssFreeB to free all message blocks and their
924 *              corresponding data blocks for the specified
925 *              message.
926 *
927 *       Ret:   Void
928 *
929 *       Notes:
930 *
931 *       File:  ss_strm.c
932 *
933 */
934 Void ssFreeMsg
935 (
936 SsMblk *mp                      /* message block */
937 )
938 {
939    SsMblk *bp;                  /* mblk for iteration */
940
941    /* free all the message blocks in the message */
942    while (mp)
943    {
944       bp = mp;
945       mp = mp->b_cont;
946       ssFreeB(bp);
947    }
948
949    return;
950 } /* ssFreeMsg */
951
952 \f
953 /*
954 *
955 *       Fun:   ssLinkB
956 *
957 *       Desc:  Puts the second specified message at the tail of
958 *              the first specified message.
959 *
960 *       Ret:   Void
961 *
962 *       Notes:
963 *
964 *       File:  ss_strm.c
965 *
966 */
967 Void ssLinkB
968 (
969 SsMblk *mp,                     /* first message block */
970 SsMblk *bp                      /* second message block */
971 )
972 {
973
974 #if (ERRCLASS & ERRCLS_INT_PAR)
975    if (mp == NULLP  ||  bp == NULLP)
976    {
977       SSLOGERROR(ERRCLS_INT_PAR, ESS345, ERRZERO, "Null pointer");
978       return;
979    }
980 #endif
981
982
983    /* run down to the end of the message */
984    while (mp->b_cont)
985    {
986       mp = mp->b_cont;
987    }
988
989
990    /* link in the passed mblock */
991    mp->b_cont = bp;
992
993    return;
994 } /* ssLinkB */
995
996 \f
997 /*
998 *
999 *       Fun:   ssMsgDSize
1000 *
1001 *       Desc:  Returns the number of bytes of data in the
1002 *              specified message.
1003 *
1004 *       Ret:   S32      - number of bytes
1005 *
1006 *       Notes:
1007 *
1008 *       File:  ss_strm.c
1009 *
1010 */
1011 S32 ssMsgDSize
1012 (
1013 SsMblk *mp                      /* message block */
1014 )
1015 {
1016    S32 n;                       /* temporary */
1017    S32 size;                    /* size of data */
1018
1019    /* for all blocks that are of type data, count the bytes */
1020    size = 0;
1021    while (mp)
1022    {
1023       if (mp->b_datap->db_type == SS_M_DATA)
1024       {
1025          n = mp->b_wptr - mp->b_rptr;
1026          if (n > 0)
1027          {
1028             size += n;
1029          }
1030       }
1031
1032       mp = mp->b_cont;
1033    }
1034
1035
1036    return (size);
1037 } /* ssMsgDSize */
1038
1039 \f
1040 /*
1041 *
1042 *       Fun:   ssPullupMsg
1043 *
1044 *       Desc:  Concatenates and aligns the first 'len' bytes
1045 *              of the specified message into a single, contiguous
1046 *              message block.
1047 *
1048 *       Ret:   1        - success
1049 *              0        - failure
1050 *
1051 *       Notes:
1052 *
1053 *       File:  ss_strm.c
1054 *
1055 */
1056 S32 ssPullupMsg
1057 (
1058 SsMblk *mp,                     /* message block */
1059 S32 len                         /* number of bytes to align */
1060 )
1061 {
1062    SsMblk *bp;                  /* mblk for iteration */
1063    SsMblk *newbp;               /* the new mblk */
1064    SsMblk *prev;                /* mblk of same type */
1065    uint8_t *base;                    /* for swapping data buffers */
1066    uint8_t *lim;                     /* for swapping data buffers */
1067    uint8_t *rptr;                    /* for swapping data buffers */
1068    uint8_t *wptr;                    /* for swapping data buffers */
1069         /* ss008.301 */
1070 #ifdef SS_DBLK_FREE_RTN
1071    SsFrtn *frtn;                /* for swapping data buffers */
1072 #endif   
1073    S32 mLen;                    /* number of bytes in all blocks of same type */
1074    S32 m;                       /* temporary */
1075    S32 n;                       /* temporary */
1076    uint8_t type;                     /* message type */
1077
1078 #if (ERRCLASS & ERRCLS_INT_PAR)
1079    if (mp == NULLP)
1080    {
1081       SSLOGERROR(ERRCLS_INT_PAR, ESS346, ERRZERO, "Null pointer");
1082       return (0);
1083    }
1084    
1085    if (len < -1)
1086    {
1087       SSLOGERROR(ERRCLS_INT_PAR, ESS347, len, "Invalid length");
1088       return (0);
1089    }
1090 #endif
1091
1092
1093    /* count the number of bytes in all blocks of the same type */
1094    bp = mp;
1095    mLen = 0;
1096    type = bp->b_datap->db_type;
1097    while (bp  &&  bp->b_datap->db_type == type)
1098    {
1099       n = bp->b_wptr - bp->b_rptr;
1100       if (n > 0)
1101       {
1102          mLen += n;
1103       }
1104
1105       bp = bp->b_cont;
1106    }
1107
1108    /* if -1 has been passed, we want to pull up all bytes */
1109    if (len == -1)
1110    {
1111       len = mLen;
1112    }
1113
1114    if (len == 0)
1115    {
1116       return (1);
1117    }
1118
1119
1120    /* do we have enough bytes to pull up? */
1121    if (len < 0  ||  len > mLen)
1122    {
1123       return (0);
1124    }
1125
1126
1127    /* allocate a new message of the required size */
1128    newbp = ssAllocB(len, 0);
1129    if (newbp == NULLP)
1130    {
1131       return (0);
1132    }
1133
1134    newbp->b_datap->db_type = mp->b_datap->db_type;
1135
1136
1137    /*  now we copy all the data in the blocks of the same type into
1138     *  this new message
1139     */
1140
1141    prev = NULLP;
1142    bp = mp;
1143    while (bp != NULLP)
1144    {
1145       /* if this buffer is of a different type, we just skip over it */
1146       if (bp->b_datap->db_type != newbp->b_datap->db_type)
1147       {
1148          prev = bp;
1149          bp = bp->b_cont;
1150          continue;
1151       }
1152
1153
1154       /* we have to copy this buffer */
1155       n = bp->b_wptr - bp->b_rptr;
1156       if (n > 0)
1157       {
1158          n = m = MIN(n, len);
1159          while (m > 0)
1160          {
1161             *newbp->b_wptr++ = *bp->b_rptr++;
1162             m--;
1163          }
1164
1165          len -= n;
1166       }
1167
1168
1169       /*  the buffer is copied, now--can we free it? if this the
1170        *  first buffer, we don't free it. also, if this buffer has
1171        *  something in it, we don't free it. otherwise, we link
1172        *  around this buffer, from the previous one to the next,
1173        *  and free this buffer.
1174        */
1175
1176       if (prev != NULLP  &&  bp->b_rptr == bp->b_wptr)
1177       {
1178          prev->b_cont = bp->b_cont;
1179          bp->b_cont = NULLP;
1180          ssFreeB(bp);
1181          bp = prev->b_cont;
1182       }
1183       else
1184       {
1185          prev = bp;
1186       }
1187    }
1188
1189
1190    /*  now we have to make the passed mblock point at the new data
1191     *  buffer we've just filled. then, we have to free the new
1192     *  mblock we created. also, we have to free the data buffer of
1193     *  the old mblock, we left it in there. we do this by basically
1194     *  swapping the data buffers of the passed mblock and the new
1195     *  mblock, and then freeing the new mblock.
1196     */
1197
1198    rptr = mp->b_rptr;
1199    wptr = mp->b_wptr;
1200    base = mp->b_datap->db_base;
1201    lim = mp->b_datap->db_lim;
1202 /* ss008.301 */
1203 #ifdef SS_DBLK_FREE_RTN
1204    frtn = mp->b_datap->db_frtnp;
1205 #endif   
1206
1207    mp->b_rptr = newbp->b_rptr;
1208    mp->b_wptr = newbp->b_wptr;
1209    mp->b_datap->db_base = newbp->b_datap->db_base;
1210    mp->b_datap->db_lim = newbp->b_datap->db_lim;
1211 /* ss008.301 */
1212 #ifdef SS_DBLK_FREE_RTN
1213    mp->b_datap->db_frtnp = NULLP;
1214 #endif  
1215
1216    newbp->b_rptr = rptr;
1217    newbp->b_wptr = wptr;
1218    newbp->b_datap->db_base = base;
1219    newbp->b_datap->db_lim = lim;
1220 /* ss008.301 */
1221 #ifdef SS_DBLK_FREE_RTN
1222    newbp->b_datap->db_frtnp = frtn;
1223 #endif   
1224
1225    ssFreeB(newbp);
1226
1227
1228    return (1);
1229 } /* ssPullupMsg */
1230
1231 \f
1232 /*
1233 *
1234 *       Fun:   ssRmvB
1235 *
1236 *       Desc:  Removes the specified message block from the
1237 *              specified message and restores the linkage of
1238 *              the remaining blocks in the message.
1239 *
1240 *       Ret:   non-NULL - pointer to the head of the new message
1241 *              -1       - specified message block not found in message
1242 *              NULL     - failure
1243 *
1244 *       Notes: The block removed is not freed.
1245 *
1246 *       File:  ss_strm.c
1247 *
1248 */
1249 SsMblk *ssRmvB
1250 (
1251 SsMblk *mp,                     /* message */
1252 SsMblk *bp                      /* message block */
1253 )
1254 {
1255    SsMblk *rp;                  /* mblk that will be returned */
1256
1257 #if (ERRCLASS & ERRCLS_INT_PAR)
1258    if (mp == NULLP  ||  bp == NULLP)
1259    {
1260       SSLOGERROR(ERRCLS_INT_PAR, ESS348, ERRZERO, "Null pointer");
1261       return (NULLP);
1262    }
1263 #endif
1264
1265
1266    /* we will return rp */
1267    rp = mp;
1268
1269
1270    /* if the block to be removed is the first one, its easy */
1271    if (mp == bp)
1272    {
1273       rp = mp->b_cont;
1274    }
1275    /* otherwise we run through the message, hunting */
1276    else
1277    {
1278       for (; ;)
1279       {
1280          if (mp == NULLP)
1281          {
1282             return ((SsMblk *)-1);
1283          }
1284          else if (mp->b_cont == bp)
1285          {
1286             mp->b_cont = bp->b_cont;
1287             break;
1288          }
1289          else
1290          {
1291             mp = mp->b_cont;
1292          }
1293       }
1294    }
1295
1296
1297    /* we've removed bp from the message, clear its next pointer */
1298    bp->b_cont = NULLP;
1299
1300
1301    return (rp);
1302 } /* ssRmvB */
1303
1304 \f
1305 /*
1306 *
1307 *       Fun:   ssTestB
1308 *
1309 *       Desc:  Checks for the availability of a message buffer
1310 *              of the specified size without actually retrieving
1311 *              the buffer.
1312 *
1313 *       Ret:   1        - buffer is available
1314 *              0        - not available
1315 *
1316 *       Notes: Is currently a hack that allocates a message and
1317 *              frees it.
1318 *
1319 *       File:  ss_strm.c
1320 *
1321 */
1322 S32 ssTestB
1323 (
1324 S32 size,                       /* size required */
1325 uint32_t pri                         /* priority of the message buffer */
1326 )
1327 {
1328    SsMblk *bp;                  /* mblk for iteration */
1329
1330    bp = ssAllocB(size, pri);
1331    if (bp)
1332    {
1333       ssFreeB(bp);
1334       return (1);
1335    }
1336
1337
1338    return (0);
1339 } /* ssTestB */
1340
1341 \f
1342 /*
1343 *
1344 *       Fun:   ssUnlinkB
1345 *
1346 *       Desc:  Removes the first message block pointed at
1347 *              by the specified message and returns a pointer
1348 *              to the head of the resultant message.
1349 *
1350 *       Ret:   non-NULL - head of the new message
1351 *              NULL     - failure
1352 *
1353 *       Notes:
1354 *
1355 *       File:  ss_strm.c
1356 *
1357 */
1358 SsMblk *ssUnlinkB
1359 (
1360 SsMblk *mp                      /* message */
1361 )
1362 {
1363    SsMblk *bp;                  /* mblk for iteration */
1364
1365 #if (ERRCLASS & ERRCLS_INT_PAR)
1366    if (mp == NULLP)
1367    {
1368       SSLOGERROR(ERRCLS_INT_PAR, ESS349, ERRZERO, "Null pointer");
1369       return (NULLP);
1370    }
1371 #endif
1372
1373
1374    /* does this need a comment? ;) */
1375    bp = mp->b_cont;
1376    mp->b_cont = NULLP;
1377
1378
1379    return (bp);
1380 } /* ssUnlinkB */
1381
1382 /**********************************************************************
1383          End of file
1384  **********************************************************************/