ObjFW  Check-in [e45e320379]

Overview
Comment:Handle pthread attrs being unavailable

This is the case on HP-UX, where pthread_attr_init() returns ENOSYS.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e45e3203793f896ccf4e6298308d5b48ef8d744fc0b1a2cd82d05dea4274979c
User & Date: js on 2021-01-01 18:49:42
Other Links: manifest | tags
Context
2021-01-01
21:43
runtime/exception.m: Implement DW_EH_PE_aligned check-in: 029db9e275 user: js tags: trunk
18:49
Handle pthread attrs being unavailable check-in: e45e320379 user: js tags: trunk
18:36
Better fallback asprintf() implementation check-in: 7267f55840 user: js tags: trunk
Changes

Modified src/platform/posix/thread.m from [08a22e6008] to [e7022e7dec].

40
41
42
43
44
45
46
47

48
49

50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65

66
67
68
69
70

71
72
73
74
75
76
77
40
41
42
43
44
45
46

47
48

49
50
51
52
53
54
55

56
57
58
59
60
61
62
63
64

65
66
67
68
69

70
71
72
73
74
75
76
77







-
+

-
+






-
+








-
+




-
+








/*
 * This is done here to make sure this is done as early as possible in the main
 * thread.
 */
OF_CONSTRUCTOR()
{
	pthread_attr_t pattr;
	pthread_attr_t attr;

	if (pthread_attr_init(&pattr) == 0) {
	if (pthread_attr_init(&attr) == 0) {
#ifdef HAVE_PTHREAD_ATTR_GETSCHEDPOLICY
		int policy;
#endif
		struct sched_param param;

#ifdef HAVE_PTHREAD_ATTR_GETSCHEDPOLICY
		if (pthread_attr_getschedpolicy(&pattr, &policy) == 0) {
		if (pthread_attr_getschedpolicy(&attr, &policy) == 0) {
			minPrio = sched_get_priority_min(policy);
			maxPrio = sched_get_priority_max(policy);

			if (minPrio == -1 || maxPrio == -1)
				minPrio = maxPrio = 0;
		}
#endif

		if (pthread_attr_getschedparam(&pattr, &param) != 0)
		if (pthread_attr_getschedparam(&attr, &param) != 0)
			normalPrio = param.sched_priority;
		else
			minPrio = maxPrio = 0;

		pthread_attr_destroy(&pattr);
		pthread_attr_destroy(&attr);
	}
}

static void *
functionWrapper(void *data)
{
	struct thread_ctx *ctx = data;
87
88
89
90
91
92
93
94

95



96




97
98
99
100



101
102

103
104
105
106
107
108
109
110
111
112


113
114
115






116
117
118
119
120

121
122
123
124
125
126
127

128
129
130
131
132
133
134
135
136
137
138
139
140

141
142
143
144
145
146


147
148
149
150
151
152
153
154
155
156
157
158


159

160

161
162
163
164
165
166
167
87
88
89
90
91
92
93

94
95
96
97
98

99
100
101
102
103



104
105
106
107

108
109
110
111
112
113
114
115
116
117

118
119
120


121
122
123
124
125
126
127
128
129
130

131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148
149
150

151
152
153
154
155


156
157
158
159
160
161
162
163
164
165
166
167
168

169
170
171
172

173
174
175
176
177
178
179
180







-
+

+
+
+
-
+
+
+
+

-
-
-
+
+
+

-
+









-
+
+

-
-
+
+
+
+
+
+




-
+






-
+












-
+




-
-
+
+











-
+
+

+
-
+







	return NULL;
}

int
of_thread_attr_init(of_thread_attr_t *attr)
{
	int error;
	pthread_attr_t pattr;
	pthread_attr_t POSIXAttr;

	attr->priority = 0;
	attr->stackSize = 0;

	if ((error = pthread_attr_init(&pattr)) != 0)
	if ((error = pthread_attr_init(&POSIXAttr)) != 0) {
		if (error == ENOSYS)
			return 0;

		return error;

	attr->priority = 0;
	error = pthread_attr_getstacksize(&pattr, &attr->stackSize);
	}

	error = pthread_attr_getstacksize(&POSIXAttr, &attr->stackSize);

	pthread_attr_destroy(&pattr);
	pthread_attr_destroy(&POSIXAttr);

	return error;
}

int
of_thread_new(of_thread_t *thread, const char *name, void (*function)(id),
    id object, const of_thread_attr_t *attr)
{
	int error = 0;
	pthread_attr_t pattr;
	pthread_attr_t POSIXAttr;
	bool POSIXAttrAvailable = true;

	if ((error = pthread_attr_init(&pattr)) != 0)
		return error;
	if ((error = pthread_attr_init(&POSIXAttr)) != 0) {
		if (error == ENOSYS)
			POSIXAttrAvailable = false;
		else
			return error;
	}

	@try {
		struct thread_ctx *ctx;

		if (attr != NULL) {
		if (attr != NULL && POSIXAttrAvailable) {
			struct sched_param param;

			if (attr->priority < -1 || attr->priority > 1)
				return EINVAL;

#ifdef HAVE_PTHREAD_ATTR_SETINHERITSCHED
			if ((error = pthread_attr_setinheritsched(&pattr,
			if ((error = pthread_attr_setinheritsched(&POSIXAttr,
			    PTHREAD_EXPLICIT_SCHED)) != 0)
				return error;
#endif

			if (attr->priority < 0) {
				param.sched_priority = minPrio +
				    (1.0f + attr->priority) *
				    (normalPrio - minPrio);
			} else
				param.sched_priority = normalPrio +
				    attr->priority * (maxPrio - normalPrio);

			if ((error = pthread_attr_setschedparam(&pattr,
			if ((error = pthread_attr_setschedparam(&POSIXAttr,
			    &param)) != 0)
				return error;

			if (attr->stackSize > 0) {
				if ((error = pthread_attr_setstacksize(&pattr,
				    attr->stackSize)) != 0)
				if ((error = pthread_attr_setstacksize(
				    &POSIXAttr, attr->stackSize)) != 0)
					return error;
			}
		}

		if ((ctx = malloc(sizeof(*ctx))) == NULL)
			return ENOMEM;

		ctx->function = function;
		ctx->object = object;
		ctx->name = name;

		error = pthread_create(thread, &pattr, functionWrapper, ctx);
		error = pthread_create(thread, &POSIXAttr, functionWrapper,
		    ctx);
	} @finally {
		if (POSIXAttrAvailable)
		pthread_attr_destroy(&pattr);
			pthread_attr_destroy(&POSIXAttr);
	}

	return error;
}

int
of_thread_join(of_thread_t thread)