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