2 * Copyright (c) 2013 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 #include <mach/mach_types.h>
29 #include <mach/host_info.h>
30 #include <kern/locks.h>
33 #include <pexpert/pexpert.h>
34 #include <libkern/OSAtomic.h>
37 * ECC data. Not really KPCs, but this still seems like the
38 * best home for this code.
40 * Circular buffer of events. When we fill up, drop data.
42 #define ECC_EVENT_BUFFER_COUNT 5
43 struct ecc_event ecc_data
[ECC_EVENT_BUFFER_COUNT
];
44 static uint32_t ecc_data_next_read
;
45 static uint32_t ecc_data_next_write
;
46 static boolean_t ecc_data_empty
= TRUE
; // next read == next write : empty or full?
47 static lck_grp_t
*ecc_data_lock_group
;
48 static lck_spin_t ecc_data_lock
;
49 static uint32_t ecc_correction_count
;
54 ecc_data_lock_group
= lck_grp_alloc_init("ecc-data", NULL
);
55 lck_spin_init(&ecc_data_lock
, ecc_data_lock_group
, NULL
);
60 ecc_log_get_correction_count()
62 return ecc_correction_count
;
66 ecc_log_record_event(const struct ecc_event
*ev
)
70 if (ev
->count
> ECC_EVENT_INFO_DATA_ENTRIES
) {
71 panic("Count of %u on ecc event is too large.", (unsigned)ev
->count
);
75 lck_spin_lock(&ecc_data_lock
);
77 ecc_correction_count
++;
79 if (ecc_data_next_read
== ecc_data_next_write
&& !ecc_data_empty
) {
80 lck_spin_unlock(&ecc_data_lock
);
85 bcopy(ev
, &ecc_data
[ecc_data_next_write
], sizeof(*ev
));
86 ecc_data_next_write
++;
87 ecc_data_next_write
%= ECC_EVENT_BUFFER_COUNT
;
88 ecc_data_empty
= FALSE
;
90 lck_spin_unlock(&ecc_data_lock
);
98 ecc_log_get_next_event(struct ecc_event
*ev
)
103 lck_spin_lock(&ecc_data_lock
);
105 if (ecc_data_empty
) {
106 assert(ecc_data_next_write
== ecc_data_next_read
);
108 lck_spin_unlock(&ecc_data_lock
);
113 bcopy(&ecc_data
[ecc_data_next_read
], ev
, sizeof(*ev
));
114 ecc_data_next_read
++;
115 ecc_data_next_read
%= ECC_EVENT_BUFFER_COUNT
;
117 if (ecc_data_next_read
== ecc_data_next_write
) {
118 ecc_data_empty
= TRUE
;
121 lck_spin_unlock(&ecc_data_lock
);