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