Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #ifndef INCLUDED_OPENCL_INC_OPENCL_DEVICE_SELECTION_H
11 : #define INCLUDED_OPENCL_INC_OPENCL_DEVICE_SELECTION_H
12 :
13 : #ifdef _MSC_VER
14 : #define _CRT_SECURE_NO_WARNINGS
15 : #endif
16 :
17 : #include <stdlib.h>
18 : #include <stdio.h>
19 : #include <string.h>
20 :
21 : #include <clew/clew.h>
22 :
23 : #define DS_DEVICE_NAME_LENGTH 256
24 :
25 : enum ds_status
26 : {
27 : DS_SUCCESS = 0
28 : ,DS_INVALID_PROFILE = 1000
29 : ,DS_MEMORY_ERROR
30 : , DS_INVALID_PERF_EVALUATOR_TYPE
31 : , DS_INVALID_PERF_EVALUATOR
32 : , DS_PERF_EVALUATOR_ERROR
33 : , DS_FILE_ERROR
34 : , DS_UNKNOWN_DEVICE_TYPE
35 : , DS_PROFILE_FILE_ERROR
36 : , DS_SCORE_SERIALIZER_ERROR
37 : , DS_SCORE_DESERIALIZER_ERROR
38 : };
39 :
40 : // device type
41 : enum ds_device_type
42 : {
43 : DS_DEVICE_NATIVE_CPU = 0
44 : ,DS_DEVICE_OPENCL_DEVICE
45 : };
46 :
47 :
48 : struct ds_device
49 : {
50 : ds_device_type type;
51 : cl_device_id oclDeviceID;
52 : char* oclPlatformVendor;
53 : char* oclDeviceName;
54 : char* oclDriverVersion;
55 : void* score; // a pointer to the score data, the content/format is application defined
56 : };
57 :
58 : struct ds_profile
59 : {
60 : unsigned int numDevices;
61 : ds_device* devices;
62 : const char* version;
63 : };
64 :
65 : // deallocate memory used by score
66 : typedef ds_status(* ds_score_release)(void* score);
67 0 : inline ds_status releaseDSProfile(ds_profile* profile, ds_score_release sr)
68 : {
69 0 : ds_status status = DS_SUCCESS;
70 0 : if (profile != NULL)
71 : {
72 0 : if (profile->devices != NULL && sr != NULL)
73 : {
74 : unsigned int i;
75 0 : for (i = 0; i < profile->numDevices; i++)
76 : {
77 0 : free(profile->devices[i].oclPlatformVendor);
78 0 : free(profile->devices[i].oclDeviceName);
79 0 : free(profile->devices[i].oclDriverVersion);
80 0 : status = sr(profile->devices[i].score);
81 0 : if (status != DS_SUCCESS) break;
82 : }
83 0 : free(profile->devices);
84 : }
85 0 : free(profile);
86 : }
87 0 : return status;
88 : }
89 :
90 :
91 0 : inline ds_status initDSProfile(ds_profile** p, const char* version)
92 : {
93 : int numDevices;
94 : cl_uint numPlatforms;
95 0 : cl_platform_id* platforms = NULL;
96 0 : cl_device_id* devices = NULL;
97 0 : ds_status status = DS_SUCCESS;
98 0 : ds_profile* profile = NULL;
99 : unsigned int next;
100 : unsigned int i;
101 :
102 0 : if (p == NULL) return DS_INVALID_PROFILE;
103 :
104 0 : profile = static_cast<ds_profile*>(malloc(sizeof(ds_profile)));
105 0 : if (profile == NULL) return DS_MEMORY_ERROR;
106 :
107 0 : memset(profile, 0, sizeof(ds_profile));
108 :
109 0 : clGetPlatformIDs(0, NULL, &numPlatforms);
110 0 : if (numPlatforms != 0)
111 : {
112 0 : platforms = static_cast<cl_platform_id*>(malloc(numPlatforms * sizeof(cl_platform_id)));
113 0 : if (platforms == NULL)
114 : {
115 0 : status = DS_MEMORY_ERROR;
116 0 : goto cleanup;
117 : }
118 0 : clGetPlatformIDs(numPlatforms, platforms, NULL);
119 : }
120 :
121 0 : numDevices = 0;
122 0 : for (i = 0; i < (unsigned int)numPlatforms; i++)
123 : {
124 0 : cl_uint num = 0;
125 0 : cl_int err = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, 0, NULL, &num);
126 0 : if (err != CL_SUCCESS)
127 : {
128 : /* we want to catch at least the case when the call returns
129 : * CL_DEVICE_NOT_FOUND (i.e. no devices), because some platforms
130 : * don't set num to 0 in this case; but in fact this is a good
131 : * thing to do for _any_ error returned by the call
132 : */
133 0 : num = 0;
134 : }
135 0 : numDevices += num;
136 : }
137 0 : if (numDevices != 0)
138 : {
139 0 : devices = static_cast<cl_device_id*>(malloc(numDevices * sizeof(cl_device_id)));
140 0 : if (devices == NULL)
141 : {
142 0 : status = DS_MEMORY_ERROR;
143 0 : goto cleanup;
144 : }
145 : }
146 :
147 0 : profile->numDevices = numDevices + 1; // +1 to numDevices to include the native CPU
148 0 : profile->devices = static_cast<ds_device*>(malloc(profile->numDevices * sizeof(ds_device)));
149 0 : if (profile->devices == NULL)
150 : {
151 0 : profile->numDevices = 0;
152 0 : status = DS_MEMORY_ERROR;
153 0 : goto cleanup;
154 : }
155 0 : memset(profile->devices, 0, profile->numDevices * sizeof(ds_device));
156 :
157 0 : next = 0;
158 0 : for (i = 0; i < (unsigned int)numPlatforms; i++)
159 : {
160 0 : cl_uint num = 0;
161 : unsigned j;
162 : char vendor[256];
163 0 : if (clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, sizeof(vendor), vendor, NULL) != CL_SUCCESS)
164 0 : vendor[0] = '\0';
165 0 : cl_int err = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, numDevices, devices, &num);
166 0 : if (err != CL_SUCCESS)
167 : {
168 : /* we want to catch at least the case when the call returns
169 : * CL_DEVICE_NOT_FOUND (i.e. no devices), because some platforms
170 : * don't set num to 0 in this case; but in fact this is a good
171 : * thing to do for _any_ error returned by the call
172 : */
173 0 : num = 0;
174 : }
175 0 : for (j = 0; j < num; j++, next++)
176 : {
177 : char buffer[DS_DEVICE_NAME_LENGTH];
178 : size_t length;
179 :
180 0 : profile->devices[next].type = DS_DEVICE_OPENCL_DEVICE;
181 0 : profile->devices[next].oclDeviceID = devices[j];
182 :
183 0 : profile->devices[next].oclPlatformVendor = strdup(vendor);
184 :
185 0 : clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_NAME
186 0 : , DS_DEVICE_NAME_LENGTH, &buffer, NULL);
187 0 : length = strlen(buffer);
188 0 : profile->devices[next].oclDeviceName = static_cast<char*>(malloc(length + 1));
189 0 : memcpy(profile->devices[next].oclDeviceName, buffer, length + 1);
190 :
191 0 : clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DRIVER_VERSION
192 0 : , DS_DEVICE_NAME_LENGTH, &buffer, NULL);
193 0 : length = strlen(buffer);
194 0 : profile->devices[next].oclDriverVersion = static_cast<char*>(malloc(length + 1));
195 0 : memcpy(profile->devices[next].oclDriverVersion, buffer, length + 1);
196 : }
197 : }
198 0 : profile->devices[next].type = DS_DEVICE_NATIVE_CPU;
199 0 : profile->version = version;
200 :
201 : cleanup:
202 0 : if (platforms) free(platforms);
203 0 : if (devices) free(devices);
204 0 : if (status == DS_SUCCESS)
205 : {
206 0 : *p = profile;
207 : }
208 : else
209 : {
210 0 : if (profile)
211 : {
212 0 : if (profile->devices) free(profile->devices);
213 0 : free(profile);
214 : }
215 : }
216 0 : return status;
217 : }
218 :
219 : // Pointer to a function that calculates the score of a device (ex: device->score)
220 : // update the data size of score. The encoding and the format of the score data
221 : // is implementation defined. The function should return DS_SUCCESS if there's no error to be reported.
222 : typedef ds_status(* ds_perf_evaluator)(ds_device* device, void* data);
223 :
224 : typedef enum {
225 : DS_EVALUATE_ALL
226 : , DS_EVALUATE_NEW_ONLY
227 : } ds_evaluation_type;
228 :
229 0 : inline ds_status profileDevices(ds_profile* profile, const ds_evaluation_type type,
230 : ds_perf_evaluator evaluator, void* evaluatorData, unsigned int* numUpdates)
231 : {
232 0 : ds_status status = DS_SUCCESS;
233 : unsigned int i;
234 0 : unsigned int updates = 0;
235 :
236 0 : if (profile == NULL)
237 : {
238 0 : return DS_INVALID_PROFILE;
239 : }
240 0 : if (evaluator == NULL)
241 : {
242 0 : return DS_INVALID_PERF_EVALUATOR;
243 : }
244 :
245 0 : for (i = 0; i < profile->numDevices; i++)
246 : {
247 : ds_status evaluatorStatus;
248 :
249 0 : switch (type)
250 : {
251 : case DS_EVALUATE_NEW_ONLY:
252 0 : if (profile->devices[i].score != NULL) break;
253 : // else fall through
254 : case DS_EVALUATE_ALL:
255 0 : evaluatorStatus = evaluator(profile->devices + i, evaluatorData);
256 0 : if (evaluatorStatus != DS_SUCCESS)
257 : {
258 0 : status = evaluatorStatus;
259 0 : return status;
260 : }
261 0 : updates++;
262 0 : break;
263 : default:
264 0 : return DS_INVALID_PERF_EVALUATOR_TYPE;
265 : break;
266 : };
267 : }
268 0 : if (numUpdates) *numUpdates = updates;
269 0 : return status;
270 : }
271 :
272 :
273 : #define DS_TAG_VERSION "<version>"
274 : #define DS_TAG_VERSION_END "</version>"
275 : #define DS_TAG_DEVICE "<device>"
276 : #define DS_TAG_DEVICE_END "</device>"
277 : #define DS_TAG_SCORE "<score>"
278 : #define DS_TAG_SCORE_END "</score>"
279 : #define DS_TAG_DEVICE_TYPE "<type>"
280 : #define DS_TAG_DEVICE_TYPE_END "</type>"
281 : #define DS_TAG_DEVICE_NAME "<name>"
282 : #define DS_TAG_DEVICE_NAME_END "</name>"
283 : #define DS_TAG_DEVICE_DRIVER_VERSION "<driver>"
284 : #define DS_TAG_DEVICE_DRIVER_VERSION_END "</driver>"
285 :
286 : #define DS_DEVICE_NATIVE_CPU_STRING "native_cpu"
287 :
288 : typedef ds_status(* ds_score_serializer)(ds_device* device, void** serializedScore, unsigned int* serializedScoreSize);
289 0 : inline ds_status writeProfileToFile(ds_profile* profile, ds_score_serializer serializer, const char* file)
290 : {
291 0 : ds_status status = DS_SUCCESS;
292 0 : FILE* profileFile = NULL;
293 :
294 :
295 0 : if (profile == NULL) return DS_INVALID_PROFILE;
296 :
297 0 : profileFile = fopen(file, "wb");
298 0 : if (profileFile == NULL)
299 : {
300 0 : status = DS_FILE_ERROR;
301 : }
302 : else
303 : {
304 : unsigned int i;
305 :
306 : // write version string
307 0 : fwrite(DS_TAG_VERSION, sizeof(char), strlen(DS_TAG_VERSION), profileFile);
308 0 : fwrite(profile->version, sizeof(char), strlen(profile->version), profileFile);
309 0 : fwrite(DS_TAG_VERSION_END, sizeof(char), strlen(DS_TAG_VERSION_END), profileFile);
310 0 : fwrite("\n", sizeof(char), 1, profileFile);
311 :
312 0 : for (i = 0; i < profile->numDevices && status == DS_SUCCESS; i++)
313 : {
314 : void* serializedScore;
315 : unsigned int serializedScoreSize;
316 :
317 0 : fwrite(DS_TAG_DEVICE, sizeof(char), strlen(DS_TAG_DEVICE), profileFile);
318 :
319 0 : fwrite(DS_TAG_DEVICE_TYPE, sizeof(char), strlen(DS_TAG_DEVICE_TYPE), profileFile);
320 0 : fwrite(&profile->devices[i].type, sizeof(ds_device_type), 1, profileFile);
321 0 : fwrite(DS_TAG_DEVICE_TYPE_END, sizeof(char), strlen(DS_TAG_DEVICE_TYPE_END), profileFile);
322 :
323 0 : switch (profile->devices[i].type)
324 : {
325 : case DS_DEVICE_NATIVE_CPU:
326 : {
327 : // There's no need to emit a device name for the native CPU device.
328 : /*
329 : fwrite(DS_TAG_DEVICE_NAME, sizeof(char), strlen(DS_TAG_DEVICE_NAME), profileFile);
330 : fwrite(DS_DEVICE_NATIVE_CPU_STRING,sizeof(char),strlen(DS_DEVICE_NATIVE_CPU_STRING), profileFile);
331 : fwrite(DS_TAG_DEVICE_NAME_END, sizeof(char), strlen(DS_TAG_DEVICE_NAME_END), profileFile);
332 : */
333 : }
334 0 : break;
335 : case DS_DEVICE_OPENCL_DEVICE:
336 : {
337 0 : fwrite(DS_TAG_DEVICE_NAME, sizeof(char), strlen(DS_TAG_DEVICE_NAME), profileFile);
338 0 : fwrite(profile->devices[i].oclDeviceName, sizeof(char), strlen(profile->devices[i].oclDeviceName), profileFile);
339 0 : fwrite(DS_TAG_DEVICE_NAME_END, sizeof(char), strlen(DS_TAG_DEVICE_NAME_END), profileFile);
340 :
341 0 : fwrite(DS_TAG_DEVICE_DRIVER_VERSION, sizeof(char), strlen(DS_TAG_DEVICE_DRIVER_VERSION), profileFile);
342 0 : fwrite(profile->devices[i].oclDriverVersion, sizeof(char), strlen(profile->devices[i].oclDriverVersion), profileFile);
343 0 : fwrite(DS_TAG_DEVICE_DRIVER_VERSION_END, sizeof(char), strlen(DS_TAG_DEVICE_DRIVER_VERSION_END), profileFile);
344 : }
345 0 : break;
346 : default:
347 0 : break;
348 : };
349 :
350 0 : fwrite(DS_TAG_SCORE, sizeof(char), strlen(DS_TAG_SCORE), profileFile);
351 0 : status = serializer(profile->devices + i, &serializedScore, &serializedScoreSize);
352 0 : if (status == DS_SUCCESS && serializedScore != NULL && serializedScoreSize > 0)
353 : {
354 0 : fwrite(serializedScore, sizeof(char), serializedScoreSize, profileFile);
355 0 : free(serializedScore);
356 : }
357 0 : fwrite(DS_TAG_SCORE_END, sizeof(char), strlen(DS_TAG_SCORE_END), profileFile);
358 0 : fwrite(DS_TAG_DEVICE_END, sizeof(char), strlen(DS_TAG_DEVICE_END), profileFile);
359 0 : fwrite("\n", sizeof(char), 1, profileFile);
360 : }
361 0 : fclose(profileFile);
362 : }
363 0 : return status;
364 : }
365 :
366 :
367 0 : inline ds_status readProFile(const char* fileName, char** content, size_t* contentSize)
368 : {
369 0 : FILE* input = NULL;
370 0 : size_t size = 0;
371 0 : char* binary = NULL;
372 0 : long pos = -1;
373 :
374 0 : *contentSize = 0;
375 0 : *content = NULL;
376 :
377 0 : input = fopen(fileName, "rb");
378 0 : if (input == NULL)
379 : {
380 0 : return DS_FILE_ERROR;
381 : }
382 :
383 0 : fseek(input, 0L, SEEK_END);
384 0 : pos = ftell(input);
385 0 : if (pos < 0)
386 : {
387 0 : fclose(input);
388 0 : return DS_FILE_ERROR;
389 : }
390 :
391 0 : size = pos;
392 0 : rewind(input);
393 0 : binary = static_cast<char*>(malloc(size));
394 0 : if (binary == NULL)
395 : {
396 0 : fclose(input);
397 0 : return DS_FILE_ERROR;
398 : }
399 0 : size_t bytesRead = fread(binary, sizeof(char), size, input);
400 : (void) bytesRead; // avoid warning
401 0 : fclose(input);
402 :
403 0 : *contentSize = size;
404 0 : *content = binary;
405 0 : return DS_SUCCESS;
406 : }
407 :
408 :
409 0 : inline const char* findString(const char* contentStart, const char* contentEnd, const char* string)
410 : {
411 : size_t stringLength;
412 : const char* currentPosition;
413 : const char* found;
414 0 : found = NULL;
415 0 : stringLength = strlen(string);
416 0 : currentPosition = contentStart;
417 0 : for (currentPosition = contentStart; currentPosition < contentEnd; currentPosition++)
418 : {
419 0 : if (*currentPosition == string[0])
420 : {
421 0 : if (currentPosition + stringLength < contentEnd)
422 : {
423 0 : if (strncmp(currentPosition, string, stringLength) == 0)
424 : {
425 0 : found = currentPosition;
426 0 : break;
427 : }
428 : }
429 : }
430 : }
431 0 : return found;
432 : }
433 :
434 :
435 : typedef ds_status(* ds_score_deserializer)(ds_device* device, const unsigned char* serializedScore, unsigned int serializedScoreSize);
436 0 : inline ds_status readProfileFromFile(ds_profile* profile, ds_score_deserializer deserializer, const char* file)
437 : {
438 :
439 0 : ds_status status = DS_SUCCESS;
440 0 : char* contentStart = NULL;
441 0 : const char* contentEnd = NULL;
442 : size_t contentSize;
443 :
444 0 : if (profile == NULL) return DS_INVALID_PROFILE;
445 :
446 0 : status = readProFile(file, &contentStart, &contentSize);
447 0 : if (status == DS_SUCCESS)
448 : {
449 : const char* currentPosition;
450 : const char* dataStart;
451 : const char* dataEnd;
452 : size_t versionStringLength;
453 :
454 0 : contentEnd = contentStart + contentSize;
455 0 : currentPosition = contentStart;
456 :
457 :
458 : // parse the version string
459 0 : dataStart = findString(currentPosition, contentEnd, DS_TAG_VERSION);
460 0 : if (dataStart == NULL)
461 : {
462 0 : status = DS_PROFILE_FILE_ERROR;
463 0 : goto cleanup;
464 : }
465 0 : dataStart += strlen(DS_TAG_VERSION);
466 :
467 0 : dataEnd = findString(dataStart, contentEnd, DS_TAG_VERSION_END);
468 0 : if (dataEnd == NULL)
469 : {
470 0 : status = DS_PROFILE_FILE_ERROR;
471 0 : goto cleanup;
472 : }
473 :
474 0 : versionStringLength = strlen(profile->version);
475 0 : if (versionStringLength != static_cast<size_t>(dataEnd - dataStart)
476 0 : || strncmp(profile->version, dataStart, versionStringLength) != 0)
477 : {
478 : // version mismatch
479 0 : status = DS_PROFILE_FILE_ERROR;
480 0 : goto cleanup;
481 : }
482 0 : currentPosition = dataEnd + strlen(DS_TAG_VERSION_END);
483 :
484 : // parse the device information
485 : while (true)
486 : {
487 : unsigned int i;
488 :
489 : const char* deviceTypeStart;
490 : const char* deviceTypeEnd;
491 : ds_device_type deviceType;
492 :
493 : const char* deviceNameStart;
494 : const char* deviceNameEnd;
495 :
496 : const char* deviceScoreStart;
497 : const char* deviceScoreEnd;
498 :
499 : const char* deviceDriverStart;
500 : const char* deviceDriverEnd;
501 :
502 0 : dataStart = findString(currentPosition, contentEnd, DS_TAG_DEVICE);
503 0 : if (dataStart == NULL)
504 : {
505 : // nothing useful remain, quit...
506 0 : break;
507 : }
508 0 : dataStart += strlen(DS_TAG_DEVICE);
509 0 : dataEnd = findString(dataStart, contentEnd, DS_TAG_DEVICE_END);
510 0 : if (dataEnd == NULL)
511 : {
512 0 : status = DS_PROFILE_FILE_ERROR;
513 0 : goto cleanup;
514 : }
515 :
516 : // parse the device type
517 0 : deviceTypeStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_TYPE);
518 0 : if (deviceTypeStart == NULL)
519 : {
520 0 : status = DS_PROFILE_FILE_ERROR;
521 0 : goto cleanup;
522 : }
523 0 : deviceTypeStart += strlen(DS_TAG_DEVICE_TYPE);
524 0 : deviceTypeEnd = findString(deviceTypeStart, contentEnd, DS_TAG_DEVICE_TYPE_END);
525 0 : if (deviceTypeEnd == NULL)
526 : {
527 0 : status = DS_PROFILE_FILE_ERROR;
528 0 : goto cleanup;
529 : }
530 0 : memcpy(&deviceType, deviceTypeStart, sizeof(ds_device_type));
531 :
532 :
533 : // parse the device name
534 0 : if (deviceType == DS_DEVICE_OPENCL_DEVICE)
535 : {
536 :
537 0 : deviceNameStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_NAME);
538 0 : if (deviceNameStart == NULL)
539 : {
540 0 : status = DS_PROFILE_FILE_ERROR;
541 0 : goto cleanup;
542 : }
543 0 : deviceNameStart += strlen(DS_TAG_DEVICE_NAME);
544 0 : deviceNameEnd = findString(deviceNameStart, contentEnd, DS_TAG_DEVICE_NAME_END);
545 0 : if (deviceNameEnd == NULL)
546 : {
547 0 : status = DS_PROFILE_FILE_ERROR;
548 0 : goto cleanup;
549 : }
550 :
551 :
552 0 : deviceDriverStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_DRIVER_VERSION);
553 0 : if (deviceDriverStart == NULL)
554 : {
555 0 : status = DS_PROFILE_FILE_ERROR;
556 0 : goto cleanup;
557 : }
558 0 : deviceDriverStart += strlen(DS_TAG_DEVICE_DRIVER_VERSION);
559 0 : deviceDriverEnd = findString(deviceDriverStart, contentEnd, DS_TAG_DEVICE_DRIVER_VERSION_END);
560 0 : if (deviceDriverEnd == NULL)
561 : {
562 0 : status = DS_PROFILE_FILE_ERROR;
563 0 : goto cleanup;
564 : }
565 :
566 :
567 : // check if this device is on the system
568 0 : for (i = 0; i < profile->numDevices; i++)
569 : {
570 0 : if (profile->devices[i].type == DS_DEVICE_OPENCL_DEVICE)
571 : {
572 : size_t actualDeviceNameLength;
573 : size_t driverVersionLength;
574 :
575 0 : actualDeviceNameLength = strlen(profile->devices[i].oclDeviceName);
576 0 : driverVersionLength = strlen(profile->devices[i].oclDriverVersion);
577 0 : if (actualDeviceNameLength == static_cast<size_t>(deviceNameEnd - deviceNameStart)
578 0 : && driverVersionLength == static_cast<size_t>(deviceDriverEnd - deviceDriverStart)
579 0 : && strncmp(profile->devices[i].oclDeviceName, deviceNameStart, actualDeviceNameLength) == 0
580 0 : && strncmp(profile->devices[i].oclDriverVersion, deviceDriverStart, driverVersionLength) == 0)
581 : {
582 :
583 0 : deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
584 0 : if (deviceScoreStart == NULL)
585 : {
586 0 : status = DS_PROFILE_FILE_ERROR;
587 0 : goto cleanup;
588 : }
589 0 : deviceScoreStart += strlen(DS_TAG_SCORE);
590 0 : deviceScoreEnd = findString(deviceScoreStart, contentEnd, DS_TAG_SCORE_END);
591 0 : status = deserializer(profile->devices + i, reinterpret_cast<const unsigned char*>(deviceScoreStart), deviceScoreEnd - deviceScoreStart);
592 0 : if (status != DS_SUCCESS)
593 : {
594 0 : goto cleanup;
595 : }
596 : }
597 : }
598 : }
599 :
600 : }
601 0 : else if (deviceType == DS_DEVICE_NATIVE_CPU)
602 : {
603 0 : for (i = 0; i < profile->numDevices; i++)
604 : {
605 0 : if (profile->devices[i].type == DS_DEVICE_NATIVE_CPU)
606 : {
607 0 : deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
608 0 : if (deviceScoreStart == NULL)
609 : {
610 0 : status = DS_PROFILE_FILE_ERROR;
611 0 : goto cleanup;
612 : }
613 0 : deviceScoreStart += strlen(DS_TAG_SCORE);
614 0 : deviceScoreEnd = findString(deviceScoreStart, contentEnd, DS_TAG_SCORE_END);
615 0 : status = deserializer(profile->devices + i, reinterpret_cast<const unsigned char*>(deviceScoreStart), deviceScoreEnd - deviceScoreStart);
616 0 : if (status != DS_SUCCESS)
617 : {
618 0 : goto cleanup;
619 : }
620 : }
621 : }
622 : }
623 :
624 : // skip over the current one to find the next device
625 0 : currentPosition = dataEnd + strlen(DS_TAG_DEVICE_END);
626 0 : }
627 : }
628 : cleanup:
629 0 : if (contentStart != NULL) free(contentStart);
630 0 : if (status != DS_SUCCESS)
631 0 : return status;
632 :
633 : // Check that all the devices present had valid cached scores. If
634 : // not, return DS_INVALID_PROFILE and let the caller re-evaluate
635 : // scores for present devices, and write a new profile file.
636 0 : for (unsigned int i = 0; i < profile->numDevices; i++)
637 0 : if (profile->devices[i].score == NULL)
638 0 : return DS_INVALID_PROFILE;
639 :
640 0 : return DS_SUCCESS;
641 : }
642 :
643 : inline ds_status getNumDeviceWithEmptyScore(ds_profile* profile, unsigned int* num)
644 : {
645 : unsigned int i;
646 : if (profile == NULL || num == NULL) return DS_MEMORY_ERROR;
647 : *num = 0;
648 : for (i = 0; i < profile->numDevices; i++)
649 : {
650 : if (profile->devices[i].score == NULL)
651 : {
652 : (*num)++;
653 : }
654 : }
655 : return DS_SUCCESS;
656 : }
657 :
658 : #endif
659 :
660 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|