100efb5e1SYuri Pankov /*
200efb5e1SYuri Pankov  * Copyright (c) 2017 Juniper Networks.  All rights reserved.
300efb5e1SYuri Pankov  *
400efb5e1SYuri Pankov  * Redistribution and use in source and binary forms, with or without
500efb5e1SYuri Pankov  * modification, are permitted provided that the following conditions
600efb5e1SYuri Pankov  * are met:
700efb5e1SYuri Pankov  * 1. Redistributions of source code must retain the above copyright
800efb5e1SYuri Pankov  *    notice, this list of conditions and the following disclaimer.
900efb5e1SYuri Pankov  * 2. Redistributions in binary form must reproduce the above copyright
1000efb5e1SYuri Pankov  *    notice, this list of conditions and the following disclaimer in the
1100efb5e1SYuri Pankov  *    documentation and/or other materials provided with the distribution.
1200efb5e1SYuri Pankov  *
1300efb5e1SYuri Pankov  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1400efb5e1SYuri Pankov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1500efb5e1SYuri Pankov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1600efb5e1SYuri Pankov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1700efb5e1SYuri Pankov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1800efb5e1SYuri Pankov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1900efb5e1SYuri Pankov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2000efb5e1SYuri Pankov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2100efb5e1SYuri Pankov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2200efb5e1SYuri Pankov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2300efb5e1SYuri Pankov  * SUCH DAMAGE.
2400efb5e1SYuri Pankov  */
2500efb5e1SYuri Pankov 
2600efb5e1SYuri Pankov /*
2700efb5e1SYuri Pankov  * Copyright 2018 Nexenta Systems, Inc.
2800efb5e1SYuri Pankov  */
2900efb5e1SYuri Pankov 
30acab0a4fSYuri Pankov #define	__STDC_WANT_LIB_EXT1__	1
31acab0a4fSYuri Pankov 
3200efb5e1SYuri Pankov #include "lint.h"
3300efb5e1SYuri Pankov 
3400efb5e1SYuri Pankov #include <sys/types.h>
3500efb5e1SYuri Pankov #include <errno.h>
3600efb5e1SYuri Pankov #include <stddef.h>
3700efb5e1SYuri Pankov #include <stdlib.h>
3800efb5e1SYuri Pankov #include <string.h>
3900efb5e1SYuri Pankov #include <synch.h>
4000efb5e1SYuri Pankov #include <thread.h>
4100efb5e1SYuri Pankov #include <unistd.h>
4200efb5e1SYuri Pankov 
4300efb5e1SYuri Pankov #include "libc.h"
4400efb5e1SYuri Pankov 
4500efb5e1SYuri Pankov /*
4600efb5e1SYuri Pankov  * Rationale recommends allocating new memory each time.
4700efb5e1SYuri Pankov  */
4800efb5e1SYuri Pankov static constraint_handler_t *_ch = NULL;
4900efb5e1SYuri Pankov static mutex_t ch_lock = ERRORCHECKMUTEX;
5000efb5e1SYuri Pankov 
5100efb5e1SYuri Pankov constraint_handler_t
set_constraint_handler_s(constraint_handler_t handler)5200efb5e1SYuri Pankov set_constraint_handler_s(constraint_handler_t handler)
5300efb5e1SYuri Pankov {
5400efb5e1SYuri Pankov 	constraint_handler_t *new, *old, ret;
5500efb5e1SYuri Pankov 
5600efb5e1SYuri Pankov 	new = malloc(sizeof (constraint_handler_t));
5700efb5e1SYuri Pankov 	if (new == NULL)
5800efb5e1SYuri Pankov 		return (NULL);
5900efb5e1SYuri Pankov 	*new = handler;
6000efb5e1SYuri Pankov 	mutex_enter(&ch_lock);
6100efb5e1SYuri Pankov 	old = _ch;
6200efb5e1SYuri Pankov 	_ch = new;
6300efb5e1SYuri Pankov 	mutex_exit(&ch_lock);
6400efb5e1SYuri Pankov 	if (old == NULL) {
6500efb5e1SYuri Pankov 		ret = NULL;
6600efb5e1SYuri Pankov 	} else {
6700efb5e1SYuri Pankov 		ret = *old;
6800efb5e1SYuri Pankov 		free(old);
6900efb5e1SYuri Pankov 	}
7000efb5e1SYuri Pankov 	return (ret);
7100efb5e1SYuri Pankov }
7200efb5e1SYuri Pankov 
7300efb5e1SYuri Pankov void
abort_handler_s(const char * _RESTRICT_KYWD msg,void * _RESTRICT_KYWD ptr __unused,errno_t error __unused)7400efb5e1SYuri Pankov abort_handler_s(const char *_RESTRICT_KYWD msg,
75*4a38094cSToomas Soome     void *_RESTRICT_KYWD ptr __unused, errno_t error __unused)
7600efb5e1SYuri Pankov {
7700efb5e1SYuri Pankov 	common_panic("abort_handler_s: ", msg);
7800efb5e1SYuri Pankov }
7900efb5e1SYuri Pankov 
8000efb5e1SYuri Pankov void
ignore_handler_s(const char * _RESTRICT_KYWD msg __unused,void * _RESTRICT_KYWD ptr __unused,errno_t error __unused)81*4a38094cSToomas Soome ignore_handler_s(const char *_RESTRICT_KYWD msg __unused,
82*4a38094cSToomas Soome     void *_RESTRICT_KYWD ptr __unused, errno_t error __unused)
8300efb5e1SYuri Pankov {
8400efb5e1SYuri Pankov }
8500efb5e1SYuri Pankov 
8600efb5e1SYuri Pankov void
__throw_constraint_handler_s(const char * _RESTRICT_KYWD msg,errno_t error)8700efb5e1SYuri Pankov __throw_constraint_handler_s(const char *_RESTRICT_KYWD msg, errno_t error)
8800efb5e1SYuri Pankov {
8900efb5e1SYuri Pankov 	constraint_handler_t ch;
9000efb5e1SYuri Pankov 
9100efb5e1SYuri Pankov 	mutex_enter(&ch_lock);
9200efb5e1SYuri Pankov 	ch = (_ch != NULL) ? *_ch : NULL;
9300efb5e1SYuri Pankov 	mutex_exit(&ch_lock);
9400efb5e1SYuri Pankov 	if (ch != NULL) {
9500efb5e1SYuri Pankov 		ch(msg, NULL, error);
9600efb5e1SYuri Pankov 	} else {
9700efb5e1SYuri Pankov 		/*
9800efb5e1SYuri Pankov 		 * If current handler is NULL (there were no calls to
9900efb5e1SYuri Pankov 		 * set_constraint_handler_s(), or it was called with NULL
10000efb5e1SYuri Pankov 		 * pointer handler argument), call default constraint handler
10100efb5e1SYuri Pankov 		 * per K.3.6.1.1 points 4 and 5.
10200efb5e1SYuri Pankov 		 *
10300efb5e1SYuri Pankov 		 * This implementation defines abort_handler_s() as default.
10400efb5e1SYuri Pankov 		 */
10500efb5e1SYuri Pankov 		abort_handler_s(msg, NULL, error);
10600efb5e1SYuri Pankov 	}
10700efb5e1SYuri Pankov }
108