Annotation of kernel/machdep/i386/libc/memset.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved.
                     26:  *
                     27:  *      File:   libc/i386/ansi/memset.c
                     28:  *      Author: Bruce Martin, NeXT Computer, Inc.
                     29:  *
                     30:  *      This file contains machine dependent code for block compares
                     31:  *      on NeXT i386-based products.  Currently tuned for the i486.
                     32:  *
                     33:  *     This code is loosely based on some work done by Mike DeMoney
                     34:  *     for the m88k.
                     35:  *
                     36:  * HISTORY
                     37:  * 14-Aug-92  Bruce Martin ([email protected])
                     38:  *     Created.
                     39:  */
                     40: 
                     41: #define MIN_TO_ALIGN   32
                     42: 
                     43: /*
                     44:  * Convert a void * into a unsigned int so arithmetic can be done
                     45:  * (Technically, the gnu C compiler is tolerant of arithmetic
                     46:  * on void *, but ansi isn't; so we do this.)
                     47:  */
                     48: #define UNS(voidp)      ((unsigned int)(voidp))
                     49: 
                     50: /*
                     51:  * Number of bytes addr is past an object of 'align' size.
                     52:  */
                     53: #define BYTES_PAST_ALIGNMENT(voidp, align) \
                     54:        (UNS(voidp) & (align - 1))
                     55: 
                     56: /*
                     57:  * Bytes moved by an unrolled loop
                     58:  */
                     59: #define LOOP_STRIDE(type, unroll)      ((unroll) * sizeof(type))
                     60: 
                     61: 
                     62: /*
                     63:  * Len modulo LOOP_STRIDE
                     64:  */
                     65: #define MODULO_LOOP_UNROLL(len, type, unroll)  \
                     66:        ((len) & (LOOP_STRIDE(type, unroll) - 1) & ~(sizeof(type) - 1))
                     67: 
                     68: 
                     69: /*
                     70:  * Convert a void * + offset into char, short, int, or long long reference
                     71:  * based at that address
                     72:  */
                     73: #define CHAR(voidp, offset)    (*(char *)(UNS(voidp) + (offset)))
                     74: #define SHORT(voidp, offset)   (*(short *)(UNS(voidp) + (offset)))
                     75: #define INT(voidp, offset)     (*(int *)(UNS(voidp) + (offset)))
                     76: 
                     77: 
                     78: 
                     79: static inline void
                     80: simple_char_set(char *dst, int val, int len)
                     81: {
                     82:     switch (len) {
                     83:        case 31:        CHAR(dst, 30) = val;
                     84:        case 30:        SHORT(dst, 28) = val;
                     85:                        INT(dst, 24) = val;
                     86:                        INT(dst, 20) = val;
                     87:                        INT(dst, 16) = val;
                     88:                        INT(dst, 12) = val;
                     89:                        INT(dst, 8) = val;
                     90:                        INT(dst, 4) = val;
                     91:                        INT(dst, 0) = val;
                     92:                        break;
                     93:        case 29:        CHAR(dst, 28) = val;
                     94:        case 28:        INT(dst, 24) = val;
                     95:                        INT(dst, 20) = val;
                     96:                        INT(dst, 16) = val;
                     97:                        INT(dst, 12) = val;
                     98:                        INT(dst, 8) = val;
                     99:                        INT(dst, 4) = val;
                    100:                        INT(dst, 0) = val;
                    101:                        break;
                    102:        case 27:        CHAR(dst, 26) = val;
                    103:        case 26:        SHORT(dst, 24) = val;
                    104:                        INT(dst, 20) = val;
                    105:                        INT(dst, 16) = val;
                    106:                        INT(dst, 12) = val;
                    107:                        INT(dst, 8) = val;
                    108:                        INT(dst, 4) = val;
                    109:                        INT(dst, 0) = val;
                    110:                        break;
                    111:        case 25:        CHAR(dst, 24) = val;
                    112:        case 24:        INT(dst, 20) = val;
                    113:                        INT(dst, 16) = val;
                    114:                        INT(dst, 12) = val;
                    115:                        INT(dst, 8) = val;
                    116:                        INT(dst, 4) = val;
                    117:                        INT(dst, 0) = val;
                    118:                        break;
                    119:        case 23:        CHAR(dst, 22) = val;
                    120:        case 22:        SHORT(dst, 20) = val;
                    121:                        INT(dst, 16) = val;
                    122:                        INT(dst, 12) = val;
                    123:                        INT(dst, 8) = val;
                    124:                        INT(dst, 4) = val;
                    125:                        INT(dst, 0) = val;
                    126:                        break;
                    127:        case 21:        CHAR(dst, 20) = val;
                    128:        case 20:        INT(dst, 16) = val;
                    129:                        INT(dst, 12) = val;
                    130:                        INT(dst, 8) = val;
                    131:                        INT(dst, 4) = val;
                    132:                        INT(dst, 0) = val;
                    133:                        break;
                    134:        case 19:        CHAR(dst, 18) = val;
                    135:        case 18:        SHORT(dst, 16) = val;
                    136:                        INT(dst, 12) = val;
                    137:                        INT(dst, 8) = val;
                    138:                        INT(dst, 4) = val;
                    139:                        INT(dst, 0) = val;
                    140:                        break;
                    141:        case 17:        CHAR(dst, 16) = val;
                    142:        case 16:        INT(dst, 12) = val;
                    143:                        INT(dst, 8) = val;
                    144:                        INT(dst, 4) = val;
                    145:                        INT(dst, 0) = val;
                    146:                        break;
                    147:        case 15:        CHAR(dst, 14) = val;
                    148:        case 14:        SHORT(dst, 12) = val;
                    149:                        INT(dst, 8) = val;
                    150:                        INT(dst, 4) = val;
                    151:                        INT(dst, 0) = val;
                    152:                        break;
                    153:        case 13:        CHAR(dst, 12) = val;
                    154:        case 12:        INT(dst, 8) = val;
                    155:                        INT(dst, 4) = val;
                    156:                        INT(dst, 0) = val;
                    157:                        break;
                    158:        case 11:        CHAR(dst, 10) = val;
                    159:        case 10:        SHORT(dst, 8) = val;
                    160:                        INT(dst, 4) = val;
                    161:                        INT(dst, 0) = val;
                    162:                        break;
                    163:        case 9:         CHAR(dst, 8) = val;
                    164:        case 8:         INT(dst, 4) = val;
                    165:                        INT(dst, 0) = val;
                    166:                        break;
                    167:        case 7:         CHAR(dst, 6) = val;
                    168:        case 6:         SHORT(dst, 4) = val;
                    169:                        INT(dst, 0) = val;
                    170:                        break;
                    171:        case 5:         CHAR(dst, 4) = val;
                    172:        case 4:         INT(dst, 0) = val;
                    173:                        break;
                    174:        case 3:         CHAR(dst, 2) = val;
                    175:        case 2:         SHORT(dst, 0) = val;
                    176:                        break;
                    177:        case 1:         CHAR(dst, 0) = val;
                    178:     }
                    179:     return;
                    180: }
                    181: 
                    182: 
                    183: 
                    184: void *memset(void *, int, unsigned long);
                    185: 
                    186: void bzero(void *dst, unsigned long ulen)
                    187: {
                    188:     (void) memset(dst, 0, ulen);
                    189: }
                    190: 
                    191: void blkclr(void *dst, unsigned long ulen)
                    192: {
                    193:     (void) memset(dst, 0, ulen);
                    194: }
                    195: 
                    196: 
                    197: 
                    198: void *memset(void *dst, int val, unsigned long ulen)
                    199: {
                    200:     int len = ulen;
                    201:     void *orig_dst = dst;
                    202:     int need_to_set;
                    203:     int alignment;
                    204: 
                    205:     val |= (val << 8);
                    206:     val |= (val << 16);
                    207: 
                    208:     /* Always do a forward copy */
                    209: 
                    210:     if (len < MIN_TO_ALIGN) {
                    211:        simple_char_set(dst, val, len);
                    212:        return orig_dst;
                    213:     }
                    214: 
                    215:     if (need_to_set = BYTES_PAST_ALIGNMENT(dst, 2 * sizeof(int))) {
                    216:        need_to_set = (2 * sizeof(int)) - need_to_set;
                    217:        simple_char_set(dst, val, need_to_set);
                    218:        len -= need_to_set;
                    219:        UNS(dst) += need_to_set;
                    220:     }
                    221: 
                    222:     alignment = MODULO_LOOP_UNROLL(len, int, 8);
                    223:     UNS(dst) += alignment - LOOP_STRIDE(int, 8);
                    224:     switch (alignment) {
                    225:            do {
                    226:                        INT(dst, 0) = val;
                    227:         case 28:       INT(dst, 4) = val;
                    228:         case 24:       INT(dst, 8) = val;
                    229:         case 20:       INT(dst, 12) = val;
                    230:         case 16:       INT(dst, 16) = val;
                    231:         case 12:       INT(dst, 20) = val;
                    232:         case 8:                INT(dst, 24) = val;
                    233:         case 4:         INT(dst, 28) = val;
                    234:         case 0:
                    235:                        UNS(dst) += LOOP_STRIDE(int, 8);
                    236:                        len -= LOOP_STRIDE(int, 8);
                    237:            } while (len >= 0);
                    238:        len &= sizeof(int) - 1;
                    239:     }
                    240:        
                    241:     switch (len) {
                    242:        case 3: CHAR(dst, 2) = val;
                    243:        case 2: CHAR(dst, 1) = val;
                    244:        case 1: CHAR(dst, 0) = val;
                    245:     }
                    246: 
                    247:     return orig_dst;
                    248: }
                    249: 
                    250: #import <mach/mach_types.h>
                    251: #import <sys/errno.h>
                    252: 
                    253: /*
                    254:  * Maintain the recover field in the thread_t structure
                    255:  */
                    256: static inline void
                    257: set_recover(int (*vector)())
                    258: {
                    259:     current_thread()->recover = (vm_offset_t)vector;
                    260:     return;
                    261: }
                    262: 
                    263: static inline void
                    264: clear_recover()
                    265: {
                    266:     current_thread()->recover = 0;
                    267: }
                    268: 
                    269: void *safe_memset(void *, int, unsigned long);
                    270: 
                    271: int safe_bzero(void *dst, unsigned long ulen)
                    272: {
                    273:     if (safe_memset(dst, 0, ulen) == (void *)(-1))
                    274:        return EFAULT;
                    275:     else
                    276:        return 0;
                    277: }
                    278: 
                    279: 
                    280: void *safe_memset(void *dst, int val, unsigned long ulen)
                    281: {
                    282:     int len = ulen;
                    283:     void *orig_dst = dst;
                    284:     int need_to_set;
                    285:     int alignment;
                    286: 
                    287:     val |= (val << 8);
                    288:     val |= (val << 16);
                    289: 
                    290:     set_recover(&&do_fault);
                    291: 
                    292:     /* Always do a forward copy */
                    293: 
                    294:     if (len < MIN_TO_ALIGN) {
                    295:        simple_char_set(dst, val, len);
                    296:        clear_recover();
                    297:        return orig_dst;
                    298:     }
                    299: 
                    300:     if (need_to_set = BYTES_PAST_ALIGNMENT(dst, 2 * sizeof(int))) {
                    301:        need_to_set = (2 * sizeof(int)) - need_to_set;
                    302:        simple_char_set(dst, val, need_to_set);
                    303:        len -= need_to_set;
                    304:        UNS(dst) += need_to_set;
                    305:     }
                    306: 
                    307:     alignment = MODULO_LOOP_UNROLL(len, int, 8);
                    308:     UNS(dst) += alignment - LOOP_STRIDE(int, 8);
                    309:     switch (alignment) {
                    310:            do {
                    311:                        INT(dst, 0) = val;
                    312:         case 28:       INT(dst, 4) = val;
                    313:         case 24:       INT(dst, 8) = val;
                    314:         case 20:       INT(dst, 12) = val;
                    315:         case 16:       INT(dst, 16) = val;
                    316:         case 12:       INT(dst, 20) = val;
                    317:         case 8:                INT(dst, 24) = val;
                    318:         case 4:         INT(dst, 28) = val;
                    319:         case 0:
                    320:                        UNS(dst) += LOOP_STRIDE(int, 8);
                    321:                        len -= LOOP_STRIDE(int, 8);
                    322:            } while (len >= 0);
                    323:        len &= sizeof(int) - 1;
                    324:     }
                    325:        
                    326:     switch (len) {
                    327:        case 3: CHAR(dst, 2) = val;
                    328:        case 2: CHAR(dst, 1) = val;
                    329:        case 1: CHAR(dst, 0) = val;
                    330:     }
                    331: 
                    332:     clear_recover();
                    333:     return orig_dst;
                    334: 
                    335: do_fault:
                    336:     clear_recover();
                    337:     return (void *)(-1);
                    338: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.