Compare commits
2 Commits
master
...
private-fw
Author | SHA1 | Date | |
---|---|---|---|
|
e2305da35c | ||
|
23dd0a4649 |
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,6 +0,0 @@
|
||||
# Release tarballs.
|
||||
/glibc-*.tar.[gx]z
|
||||
# Generated (source) RPMs.
|
||||
/*.rpm
|
||||
# Expanded source trees.
|
||||
/glibc-*/
|
1054
ChangeLog.old
1054
ChangeLog.old
File diff suppressed because it is too large
Load Diff
@ -1,2 +0,0 @@
|
||||
All of the useful glibc maintainer scripts are located at:
|
||||
https://pagure.io/glibc-maintainer-scripts
|
494
SUPPORTED
494
SUPPORTED
@ -1,494 +0,0 @@
|
||||
# This file names the currently supported and somewhat tested locales.
|
||||
# If you have any additions please file a glibc bug report.
|
||||
SUPPORTED-LOCALES=\
|
||||
C.UTF-8/UTF-8 \
|
||||
aa_DJ.UTF-8/UTF-8 \
|
||||
aa_DJ/ISO-8859-1 \
|
||||
aa_ER/UTF-8 \
|
||||
aa_ER@saaho/UTF-8 \
|
||||
aa_ET/UTF-8 \
|
||||
af_ZA.UTF-8/UTF-8 \
|
||||
af_ZA/ISO-8859-1 \
|
||||
agr_PE/UTF-8 \
|
||||
ak_GH/UTF-8 \
|
||||
am_ET/UTF-8 \
|
||||
an_ES.UTF-8/UTF-8 \
|
||||
an_ES/ISO-8859-15 \
|
||||
anp_IN/UTF-8 \
|
||||
ar_AE.UTF-8/UTF-8 \
|
||||
ar_AE/ISO-8859-6 \
|
||||
ar_BH.UTF-8/UTF-8 \
|
||||
ar_BH/ISO-8859-6 \
|
||||
ar_DZ.UTF-8/UTF-8 \
|
||||
ar_DZ/ISO-8859-6 \
|
||||
ar_EG.UTF-8/UTF-8 \
|
||||
ar_EG/ISO-8859-6 \
|
||||
ar_IN/UTF-8 \
|
||||
ar_IQ.UTF-8/UTF-8 \
|
||||
ar_IQ/ISO-8859-6 \
|
||||
ar_JO.UTF-8/UTF-8 \
|
||||
ar_JO/ISO-8859-6 \
|
||||
ar_KW.UTF-8/UTF-8 \
|
||||
ar_KW/ISO-8859-6 \
|
||||
ar_LB.UTF-8/UTF-8 \
|
||||
ar_LB/ISO-8859-6 \
|
||||
ar_LY.UTF-8/UTF-8 \
|
||||
ar_LY/ISO-8859-6 \
|
||||
ar_MA.UTF-8/UTF-8 \
|
||||
ar_MA/ISO-8859-6 \
|
||||
ar_OM.UTF-8/UTF-8 \
|
||||
ar_OM/ISO-8859-6 \
|
||||
ar_QA.UTF-8/UTF-8 \
|
||||
ar_QA/ISO-8859-6 \
|
||||
ar_SA.UTF-8/UTF-8 \
|
||||
ar_SA/ISO-8859-6 \
|
||||
ar_SD.UTF-8/UTF-8 \
|
||||
ar_SD/ISO-8859-6 \
|
||||
ar_SS/UTF-8 \
|
||||
ar_SY.UTF-8/UTF-8 \
|
||||
ar_SY/ISO-8859-6 \
|
||||
ar_TN.UTF-8/UTF-8 \
|
||||
ar_TN/ISO-8859-6 \
|
||||
ar_YE.UTF-8/UTF-8 \
|
||||
ar_YE/ISO-8859-6 \
|
||||
ayc_PE/UTF-8 \
|
||||
az_AZ/UTF-8 \
|
||||
az_IR/UTF-8 \
|
||||
as_IN/UTF-8 \
|
||||
ast_ES.UTF-8/UTF-8 \
|
||||
ast_ES/ISO-8859-15 \
|
||||
be_BY.UTF-8/UTF-8 \
|
||||
be_BY/CP1251 \
|
||||
be_BY@latin/UTF-8 \
|
||||
bem_ZM/UTF-8 \
|
||||
ber_DZ/UTF-8 \
|
||||
ber_MA/UTF-8 \
|
||||
bg_BG.UTF-8/UTF-8 \
|
||||
bg_BG/CP1251 \
|
||||
bhb_IN.UTF-8/UTF-8 \
|
||||
bho_IN/UTF-8 \
|
||||
bho_NP/UTF-8 \
|
||||
bi_VU/UTF-8 \
|
||||
bn_BD/UTF-8 \
|
||||
bn_IN/UTF-8 \
|
||||
bo_CN/UTF-8 \
|
||||
bo_IN/UTF-8 \
|
||||
br_FR.UTF-8/UTF-8 \
|
||||
br_FR/ISO-8859-1 \
|
||||
br_FR@euro/ISO-8859-15 \
|
||||
brx_IN/UTF-8 \
|
||||
bs_BA.UTF-8/UTF-8 \
|
||||
bs_BA/ISO-8859-2 \
|
||||
byn_ER/UTF-8 \
|
||||
ca_AD.UTF-8/UTF-8 \
|
||||
ca_AD/ISO-8859-15 \
|
||||
ca_ES.UTF-8/UTF-8 \
|
||||
ca_ES/ISO-8859-1 \
|
||||
ca_ES@euro/ISO-8859-15 \
|
||||
ca_ES@valencia/UTF-8 \
|
||||
ca_FR.UTF-8/UTF-8 \
|
||||
ca_FR/ISO-8859-15 \
|
||||
ca_IT.UTF-8/UTF-8 \
|
||||
ca_IT/ISO-8859-15 \
|
||||
ce_RU/UTF-8 \
|
||||
chr_US/UTF-8 \
|
||||
cmn_TW/UTF-8 \
|
||||
crh_UA/UTF-8 \
|
||||
cs_CZ.UTF-8/UTF-8 \
|
||||
cs_CZ/ISO-8859-2 \
|
||||
csb_PL/UTF-8 \
|
||||
cv_RU/UTF-8 \
|
||||
cy_GB.UTF-8/UTF-8 \
|
||||
cy_GB/ISO-8859-14 \
|
||||
da_DK.UTF-8/UTF-8 \
|
||||
da_DK/ISO-8859-1 \
|
||||
da_DK.ISO-8859-15/ISO-8859-15 \
|
||||
de_AT.UTF-8/UTF-8 \
|
||||
de_AT/ISO-8859-1 \
|
||||
de_AT@euro/ISO-8859-15 \
|
||||
de_BE.UTF-8/UTF-8 \
|
||||
de_BE/ISO-8859-1 \
|
||||
de_BE@euro/ISO-8859-15 \
|
||||
de_CH.UTF-8/UTF-8 \
|
||||
de_CH/ISO-8859-1 \
|
||||
de_DE.UTF-8/UTF-8 \
|
||||
de_DE/ISO-8859-1 \
|
||||
de_DE@euro/ISO-8859-15 \
|
||||
de_IT.UTF-8/UTF-8 \
|
||||
de_IT/ISO-8859-1 \
|
||||
de_LI.UTF-8/UTF-8 \
|
||||
de_LU.UTF-8/UTF-8 \
|
||||
de_LU/ISO-8859-1 \
|
||||
de_LU@euro/ISO-8859-15 \
|
||||
doi_IN/UTF-8 \
|
||||
dsb_DE/UTF-8 \
|
||||
dv_MV/UTF-8 \
|
||||
dz_BT/UTF-8 \
|
||||
el_GR.UTF-8/UTF-8 \
|
||||
el_GR/ISO-8859-7 \
|
||||
el_GR@euro/ISO-8859-7 \
|
||||
el_CY.UTF-8/UTF-8 \
|
||||
el_CY/ISO-8859-7 \
|
||||
en_AG/UTF-8 \
|
||||
en_AU.UTF-8/UTF-8 \
|
||||
en_AU/ISO-8859-1 \
|
||||
en_BW.UTF-8/UTF-8 \
|
||||
en_BW/ISO-8859-1 \
|
||||
en_CA.UTF-8/UTF-8 \
|
||||
en_CA/ISO-8859-1 \
|
||||
en_DK.UTF-8/UTF-8 \
|
||||
en_DK/ISO-8859-1 \
|
||||
en_GB.UTF-8/UTF-8 \
|
||||
en_GB/ISO-8859-1 \
|
||||
en_GB.ISO-8859-15/ISO-8859-15 \
|
||||
en_HK.UTF-8/UTF-8 \
|
||||
en_HK/ISO-8859-1 \
|
||||
en_IE.UTF-8/UTF-8 \
|
||||
en_IE/ISO-8859-1 \
|
||||
en_IE@euro/ISO-8859-15 \
|
||||
en_IL/UTF-8 \
|
||||
en_IN/UTF-8 \
|
||||
en_NG/UTF-8 \
|
||||
en_NZ.UTF-8/UTF-8 \
|
||||
en_NZ/ISO-8859-1 \
|
||||
en_PH.UTF-8/UTF-8 \
|
||||
en_PH/ISO-8859-1 \
|
||||
en_SC.UTF-8/UTF-8 \
|
||||
en_SG.UTF-8/UTF-8 \
|
||||
en_SG/ISO-8859-1 \
|
||||
en_US.UTF-8/UTF-8 \
|
||||
en_US/ISO-8859-1 \
|
||||
en_US.ISO-8859-15/ISO-8859-15 \
|
||||
en_ZA.UTF-8/UTF-8 \
|
||||
en_ZA/ISO-8859-1 \
|
||||
en_ZM/UTF-8 \
|
||||
en_ZW.UTF-8/UTF-8 \
|
||||
en_ZW/ISO-8859-1 \
|
||||
eo/UTF-8 \
|
||||
es_AR.UTF-8/UTF-8 \
|
||||
es_AR/ISO-8859-1 \
|
||||
es_BO.UTF-8/UTF-8 \
|
||||
es_BO/ISO-8859-1 \
|
||||
es_CL.UTF-8/UTF-8 \
|
||||
es_CL/ISO-8859-1 \
|
||||
es_CO.UTF-8/UTF-8 \
|
||||
es_CO/ISO-8859-1 \
|
||||
es_CR.UTF-8/UTF-8 \
|
||||
es_CR/ISO-8859-1 \
|
||||
es_CU/UTF-8 \
|
||||
es_DO.UTF-8/UTF-8 \
|
||||
es_DO/ISO-8859-1 \
|
||||
es_EC.UTF-8/UTF-8 \
|
||||
es_EC/ISO-8859-1 \
|
||||
es_ES.UTF-8/UTF-8 \
|
||||
es_ES/ISO-8859-1 \
|
||||
es_ES@euro/ISO-8859-15 \
|
||||
es_GT.UTF-8/UTF-8 \
|
||||
es_GT/ISO-8859-1 \
|
||||
es_HN.UTF-8/UTF-8 \
|
||||
es_HN/ISO-8859-1 \
|
||||
es_MX.UTF-8/UTF-8 \
|
||||
es_MX/ISO-8859-1 \
|
||||
es_NI.UTF-8/UTF-8 \
|
||||
es_NI/ISO-8859-1 \
|
||||
es_PA.UTF-8/UTF-8 \
|
||||
es_PA/ISO-8859-1 \
|
||||
es_PE.UTF-8/UTF-8 \
|
||||
es_PE/ISO-8859-1 \
|
||||
es_PR.UTF-8/UTF-8 \
|
||||
es_PR/ISO-8859-1 \
|
||||
es_PY.UTF-8/UTF-8 \
|
||||
es_PY/ISO-8859-1 \
|
||||
es_SV.UTF-8/UTF-8 \
|
||||
es_SV/ISO-8859-1 \
|
||||
es_US.UTF-8/UTF-8 \
|
||||
es_US/ISO-8859-1 \
|
||||
es_UY.UTF-8/UTF-8 \
|
||||
es_UY/ISO-8859-1 \
|
||||
es_VE.UTF-8/UTF-8 \
|
||||
es_VE/ISO-8859-1 \
|
||||
et_EE.UTF-8/UTF-8 \
|
||||
et_EE/ISO-8859-1 \
|
||||
et_EE.ISO-8859-15/ISO-8859-15 \
|
||||
eu_ES.UTF-8/UTF-8 \
|
||||
eu_ES/ISO-8859-1 \
|
||||
eu_ES@euro/ISO-8859-15 \
|
||||
fa_IR/UTF-8 \
|
||||
ff_SN/UTF-8 \
|
||||
fi_FI.UTF-8/UTF-8 \
|
||||
fi_FI/ISO-8859-1 \
|
||||
fi_FI@euro/ISO-8859-15 \
|
||||
fil_PH/UTF-8 \
|
||||
fo_FO.UTF-8/UTF-8 \
|
||||
fo_FO/ISO-8859-1 \
|
||||
fr_BE.UTF-8/UTF-8 \
|
||||
fr_BE/ISO-8859-1 \
|
||||
fr_BE@euro/ISO-8859-15 \
|
||||
fr_CA.UTF-8/UTF-8 \
|
||||
fr_CA/ISO-8859-1 \
|
||||
fr_CH.UTF-8/UTF-8 \
|
||||
fr_CH/ISO-8859-1 \
|
||||
fr_FR.UTF-8/UTF-8 \
|
||||
fr_FR/ISO-8859-1 \
|
||||
fr_FR@euro/ISO-8859-15 \
|
||||
fr_LU.UTF-8/UTF-8 \
|
||||
fr_LU/ISO-8859-1 \
|
||||
fr_LU@euro/ISO-8859-15 \
|
||||
fur_IT/UTF-8 \
|
||||
fy_NL/UTF-8 \
|
||||
fy_DE/UTF-8 \
|
||||
ga_IE.UTF-8/UTF-8 \
|
||||
ga_IE/ISO-8859-1 \
|
||||
ga_IE@euro/ISO-8859-15 \
|
||||
gd_GB.UTF-8/UTF-8 \
|
||||
gd_GB/ISO-8859-15 \
|
||||
gez_ER/UTF-8 \
|
||||
gez_ER@abegede/UTF-8 \
|
||||
gez_ET/UTF-8 \
|
||||
gez_ET@abegede/UTF-8 \
|
||||
gl_ES.UTF-8/UTF-8 \
|
||||
gl_ES/ISO-8859-1 \
|
||||
gl_ES@euro/ISO-8859-15 \
|
||||
gu_IN/UTF-8 \
|
||||
gv_GB.UTF-8/UTF-8 \
|
||||
gv_GB/ISO-8859-1 \
|
||||
ha_NG/UTF-8 \
|
||||
hak_TW/UTF-8 \
|
||||
he_IL.UTF-8/UTF-8 \
|
||||
he_IL/ISO-8859-8 \
|
||||
hi_IN/UTF-8 \
|
||||
hif_FJ/UTF-8 \
|
||||
hne_IN/UTF-8 \
|
||||
hr_HR.UTF-8/UTF-8 \
|
||||
hr_HR/ISO-8859-2 \
|
||||
hsb_DE/ISO-8859-2 \
|
||||
hsb_DE.UTF-8/UTF-8 \
|
||||
ht_HT/UTF-8 \
|
||||
hu_HU.UTF-8/UTF-8 \
|
||||
hu_HU/ISO-8859-2 \
|
||||
hy_AM/UTF-8 \
|
||||
hy_AM.ARMSCII-8/ARMSCII-8 \
|
||||
ia_FR/UTF-8 \
|
||||
id_ID.UTF-8/UTF-8 \
|
||||
id_ID/ISO-8859-1 \
|
||||
ig_NG/UTF-8 \
|
||||
ik_CA/UTF-8 \
|
||||
is_IS.UTF-8/UTF-8 \
|
||||
is_IS/ISO-8859-1 \
|
||||
it_CH.UTF-8/UTF-8 \
|
||||
it_CH/ISO-8859-1 \
|
||||
it_IT.UTF-8/UTF-8 \
|
||||
it_IT/ISO-8859-1 \
|
||||
it_IT@euro/ISO-8859-15 \
|
||||
iu_CA/UTF-8 \
|
||||
ja_JP.EUC-JP/EUC-JP \
|
||||
ja_JP.UTF-8/UTF-8 \
|
||||
ka_GE.UTF-8/UTF-8 \
|
||||
ka_GE/GEORGIAN-PS \
|
||||
kab_DZ/UTF-8 \
|
||||
kk_KZ.UTF-8/UTF-8 \
|
||||
kk_KZ/PT154 \
|
||||
kl_GL.UTF-8/UTF-8 \
|
||||
kl_GL/ISO-8859-1 \
|
||||
km_KH/UTF-8 \
|
||||
kn_IN/UTF-8 \
|
||||
ko_KR.EUC-KR/EUC-KR \
|
||||
ko_KR.UTF-8/UTF-8 \
|
||||
kok_IN/UTF-8 \
|
||||
ks_IN/UTF-8 \
|
||||
ks_IN@devanagari/UTF-8 \
|
||||
ku_TR.UTF-8/UTF-8 \
|
||||
ku_TR/ISO-8859-9 \
|
||||
kw_GB.UTF-8/UTF-8 \
|
||||
kw_GB/ISO-8859-1 \
|
||||
ky_KG/UTF-8 \
|
||||
lb_LU/UTF-8 \
|
||||
lg_UG.UTF-8/UTF-8 \
|
||||
lg_UG/ISO-8859-10 \
|
||||
li_BE/UTF-8 \
|
||||
li_NL/UTF-8 \
|
||||
lij_IT/UTF-8 \
|
||||
ln_CD/UTF-8 \
|
||||
lo_LA/UTF-8 \
|
||||
lt_LT.UTF-8/UTF-8 \
|
||||
lt_LT/ISO-8859-13 \
|
||||
lv_LV.UTF-8/UTF-8 \
|
||||
lv_LV/ISO-8859-13 \
|
||||
lzh_TW/UTF-8 \
|
||||
mag_IN/UTF-8 \
|
||||
mai_IN/UTF-8 \
|
||||
mai_NP/UTF-8 \
|
||||
mfe_MU/UTF-8 \
|
||||
mg_MG.UTF-8/UTF-8 \
|
||||
mg_MG/ISO-8859-15 \
|
||||
mhr_RU/UTF-8 \
|
||||
mi_NZ.UTF-8/UTF-8 \
|
||||
mi_NZ/ISO-8859-13 \
|
||||
miq_NI/UTF-8 \
|
||||
mjw_IN/UTF-8 \
|
||||
mk_MK.UTF-8/UTF-8 \
|
||||
mk_MK/ISO-8859-5 \
|
||||
ml_IN/UTF-8 \
|
||||
mn_MN/UTF-8 \
|
||||
mni_IN/UTF-8 \
|
||||
mr_IN/UTF-8 \
|
||||
ms_MY.UTF-8/UTF-8 \
|
||||
ms_MY/ISO-8859-1 \
|
||||
mt_MT.UTF-8/UTF-8 \
|
||||
mt_MT/ISO-8859-3 \
|
||||
my_MM/UTF-8 \
|
||||
nan_TW/UTF-8 \
|
||||
nan_TW@latin/UTF-8 \
|
||||
nb_NO.UTF-8/UTF-8 \
|
||||
nb_NO/ISO-8859-1 \
|
||||
nds_DE/UTF-8 \
|
||||
nds_NL/UTF-8 \
|
||||
ne_NP/UTF-8 \
|
||||
nhn_MX/UTF-8 \
|
||||
niu_NU/UTF-8 \
|
||||
niu_NZ/UTF-8 \
|
||||
nl_AW/UTF-8 \
|
||||
nl_BE.UTF-8/UTF-8 \
|
||||
nl_BE/ISO-8859-1 \
|
||||
nl_BE@euro/ISO-8859-15 \
|
||||
nl_NL.UTF-8/UTF-8 \
|
||||
nl_NL/ISO-8859-1 \
|
||||
nl_NL@euro/ISO-8859-15 \
|
||||
nn_NO.UTF-8/UTF-8 \
|
||||
nn_NO/ISO-8859-1 \
|
||||
nr_ZA/UTF-8 \
|
||||
nso_ZA/UTF-8 \
|
||||
oc_FR.UTF-8/UTF-8 \
|
||||
oc_FR/ISO-8859-1 \
|
||||
om_ET/UTF-8 \
|
||||
om_KE.UTF-8/UTF-8 \
|
||||
om_KE/ISO-8859-1 \
|
||||
or_IN/UTF-8 \
|
||||
os_RU/UTF-8 \
|
||||
pa_IN/UTF-8 \
|
||||
pa_PK/UTF-8 \
|
||||
pap_AW/UTF-8 \
|
||||
pap_CW/UTF-8 \
|
||||
pl_PL.UTF-8/UTF-8 \
|
||||
pl_PL/ISO-8859-2 \
|
||||
ps_AF/UTF-8 \
|
||||
pt_BR.UTF-8/UTF-8 \
|
||||
pt_BR/ISO-8859-1 \
|
||||
pt_PT.UTF-8/UTF-8 \
|
||||
pt_PT/ISO-8859-1 \
|
||||
pt_PT@euro/ISO-8859-15 \
|
||||
quz_PE/UTF-8 \
|
||||
raj_IN/UTF-8 \
|
||||
ro_RO.UTF-8/UTF-8 \
|
||||
ro_RO/ISO-8859-2 \
|
||||
ru_RU.KOI8-R/KOI8-R \
|
||||
ru_RU.UTF-8/UTF-8 \
|
||||
ru_RU/ISO-8859-5 \
|
||||
ru_UA.UTF-8/UTF-8 \
|
||||
ru_UA/KOI8-U \
|
||||
rw_RW/UTF-8 \
|
||||
sa_IN/UTF-8 \
|
||||
sah_RU/UTF-8 \
|
||||
sat_IN/UTF-8 \
|
||||
sc_IT/UTF-8 \
|
||||
sd_IN/UTF-8 \
|
||||
sd_IN@devanagari/UTF-8 \
|
||||
se_NO/UTF-8 \
|
||||
sgs_LT/UTF-8 \
|
||||
shn_MM/UTF-8 \
|
||||
shs_CA/UTF-8 \
|
||||
si_LK/UTF-8 \
|
||||
sid_ET/UTF-8 \
|
||||
sk_SK.UTF-8/UTF-8 \
|
||||
sk_SK/ISO-8859-2 \
|
||||
sl_SI.UTF-8/UTF-8 \
|
||||
sl_SI/ISO-8859-2 \
|
||||
sm_WS/UTF-8 \
|
||||
so_DJ.UTF-8/UTF-8 \
|
||||
so_DJ/ISO-8859-1 \
|
||||
so_ET/UTF-8 \
|
||||
so_KE.UTF-8/UTF-8 \
|
||||
so_KE/ISO-8859-1 \
|
||||
so_SO.UTF-8/UTF-8 \
|
||||
so_SO/ISO-8859-1 \
|
||||
sq_AL.UTF-8/UTF-8 \
|
||||
sq_AL/ISO-8859-1 \
|
||||
sq_MK/UTF-8 \
|
||||
sr_ME/UTF-8 \
|
||||
sr_RS/UTF-8 \
|
||||
sr_RS@latin/UTF-8 \
|
||||
ss_ZA/UTF-8 \
|
||||
st_ZA.UTF-8/UTF-8 \
|
||||
st_ZA/ISO-8859-1 \
|
||||
sv_FI.UTF-8/UTF-8 \
|
||||
sv_FI/ISO-8859-1 \
|
||||
sv_FI@euro/ISO-8859-15 \
|
||||
sv_SE.UTF-8/UTF-8 \
|
||||
sv_SE/ISO-8859-1 \
|
||||
sv_SE.ISO-8859-15/ISO-8859-15 \
|
||||
sw_KE/UTF-8 \
|
||||
sw_TZ/UTF-8 \
|
||||
szl_PL/UTF-8 \
|
||||
ta_IN/UTF-8 \
|
||||
ta_LK/UTF-8 \
|
||||
tcy_IN.UTF-8/UTF-8 \
|
||||
te_IN/UTF-8 \
|
||||
tg_TJ.UTF-8/UTF-8 \
|
||||
tg_TJ/KOI8-T \
|
||||
th_TH.UTF-8/UTF-8 \
|
||||
th_TH/TIS-620 \
|
||||
the_NP/UTF-8 \
|
||||
ti_ER/UTF-8 \
|
||||
ti_ET/UTF-8 \
|
||||
tig_ER/UTF-8 \
|
||||
tk_TM/UTF-8 \
|
||||
tl_PH.UTF-8/UTF-8 \
|
||||
tl_PH/ISO-8859-1 \
|
||||
tn_ZA/UTF-8 \
|
||||
to_TO/UTF-8 \
|
||||
tpi_PG/UTF-8 \
|
||||
tr_CY.UTF-8/UTF-8 \
|
||||
tr_CY/ISO-8859-9 \
|
||||
tr_TR.UTF-8/UTF-8 \
|
||||
tr_TR/ISO-8859-9 \
|
||||
ts_ZA/UTF-8 \
|
||||
tt_RU/UTF-8 \
|
||||
tt_RU@iqtelif/UTF-8 \
|
||||
ug_CN/UTF-8 \
|
||||
uk_UA.UTF-8/UTF-8 \
|
||||
uk_UA/KOI8-U \
|
||||
unm_US/UTF-8 \
|
||||
ur_IN/UTF-8 \
|
||||
ur_PK/UTF-8 \
|
||||
uz_UZ.UTF-8/UTF-8 \
|
||||
uz_UZ/ISO-8859-1 \
|
||||
uz_UZ@cyrillic/UTF-8 \
|
||||
ve_ZA/UTF-8 \
|
||||
vi_VN/UTF-8 \
|
||||
wa_BE/ISO-8859-1 \
|
||||
wa_BE@euro/ISO-8859-15 \
|
||||
wa_BE.UTF-8/UTF-8 \
|
||||
wae_CH/UTF-8 \
|
||||
wal_ET/UTF-8 \
|
||||
wo_SN/UTF-8 \
|
||||
xh_ZA.UTF-8/UTF-8 \
|
||||
xh_ZA/ISO-8859-1 \
|
||||
yi_US.UTF-8/UTF-8 \
|
||||
yi_US/CP1255 \
|
||||
yo_NG/UTF-8 \
|
||||
yue_HK/UTF-8 \
|
||||
yuw_PG/UTF-8 \
|
||||
zh_CN.GB18030/GB18030 \
|
||||
zh_CN.GBK/GBK \
|
||||
zh_CN.UTF-8/UTF-8 \
|
||||
zh_CN/GB2312 \
|
||||
zh_HK.UTF-8/UTF-8 \
|
||||
zh_HK/BIG5-HKSCS \
|
||||
zh_SG.UTF-8/UTF-8 \
|
||||
zh_SG.GBK/GBK \
|
||||
zh_SG/GB2312 \
|
||||
zh_TW.EUC-TW/EUC-TW \
|
||||
zh_TW.UTF-8/UTF-8 \
|
||||
zh_TW/BIG5 \
|
||||
zu_ZA.UTF-8/UTF-8 \
|
||||
zu_ZA/ISO-8859-1 \
|
857
build-locale-archive.c
Normal file
857
build-locale-archive.c
Normal file
@ -0,0 +1,857 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include "../locale/hashval.h"
|
||||
#define __LC_LAST 13
|
||||
#include "../locale/locarchive.h"
|
||||
#include "../crypt/md5.h"
|
||||
|
||||
const char *alias_file = DATADIR "/locale/locale.alias";
|
||||
const char *locar_file = PREFIX "/lib/locale/locale-archive";
|
||||
const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl";
|
||||
const char *loc_path = PREFIX "/lib/locale/";
|
||||
/* Flags set by `--verbose` option. */
|
||||
int be_quiet = 1;
|
||||
int verbose = 0;
|
||||
int max_locarchive_open_retry = 10;
|
||||
const char *output_prefix;
|
||||
|
||||
/* Endianness should have been taken care of by localedef. We don't need to do
|
||||
additional swapping. We need this variable exported however, since
|
||||
locarchive.c uses it to determine if it needs to swap endianness of a value
|
||||
before writing to or reading from the archive. */
|
||||
bool swap_endianness_p = false;
|
||||
|
||||
static const char *locnames[] =
|
||||
{
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
[category] = category_name,
|
||||
#include "../locale/categories.def"
|
||||
#undef DEFINE_CATEGORY
|
||||
};
|
||||
|
||||
static int
|
||||
is_prime (unsigned long candidate)
|
||||
{
|
||||
/* No even number and none less than 10 will be passed here. */
|
||||
unsigned long int divn = 3;
|
||||
unsigned long int sq = divn * divn;
|
||||
|
||||
while (sq < candidate && candidate % divn != 0)
|
||||
{
|
||||
++divn;
|
||||
sq += 4 * divn;
|
||||
++divn;
|
||||
}
|
||||
|
||||
return candidate % divn != 0;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
next_prime (unsigned long seed)
|
||||
{
|
||||
/* Make it definitely odd. */
|
||||
seed |= 1;
|
||||
|
||||
while (!is_prime (seed))
|
||||
seed += 2;
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
void
|
||||
error (int status, int errnum, const char *message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, message);
|
||||
fflush (stdout);
|
||||
fprintf (stderr, "%s: ", program_invocation_name);
|
||||
vfprintf (stderr, message, args);
|
||||
va_end (args);
|
||||
if (errnum)
|
||||
fprintf (stderr, ": %s", strerror (errnum));
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
exit (errnum == EROFS ? 0 : status);
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc (size_t size)
|
||||
{
|
||||
void *p = malloc (size);
|
||||
if (p == NULL)
|
||||
error (EXIT_FAILURE, errno, "could not allocate %zd bytes of memory", size);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
open_tmpl_archive (struct locarhandle *ah)
|
||||
{
|
||||
struct stat64 st;
|
||||
int fd;
|
||||
struct locarhead head;
|
||||
const char *archivefname = ah->fname == NULL ? tmpl_file : ah->fname;
|
||||
|
||||
/* Open the archive. We must have exclusive write access. */
|
||||
fd = open64 (archivefname, O_RDONLY);
|
||||
if (fd == -1)
|
||||
error (EXIT_FAILURE, errno, "cannot open locale archive template file \"%s\"",
|
||||
archivefname);
|
||||
|
||||
if (fstat64 (fd, &st) < 0)
|
||||
error (EXIT_FAILURE, errno, "cannot stat locale archive template file \"%s\"",
|
||||
archivefname);
|
||||
|
||||
/* Read the header. */
|
||||
if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head))
|
||||
error (EXIT_FAILURE, errno, "cannot read archive header");
|
||||
|
||||
ah->fd = fd;
|
||||
ah->mmaped = (head.sumhash_offset
|
||||
+ head.sumhash_size * sizeof (struct sumhashent));
|
||||
if (ah->mmaped > (unsigned long) st.st_size)
|
||||
error (EXIT_FAILURE, 0, "locale archive template file truncated");
|
||||
ah->mmaped = st.st_size;
|
||||
ah->reserved = st.st_size;
|
||||
|
||||
/* Now we know how large the administrative information part is.
|
||||
Map all of it. */
|
||||
ah->addr = mmap64 (NULL, ah->mmaped, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (ah->addr == MAP_FAILED)
|
||||
error (EXIT_FAILURE, errno, "cannot map archive header");
|
||||
}
|
||||
|
||||
/* Open the locale archive. */
|
||||
extern void open_archive (struct locarhandle *ah, bool readonly);
|
||||
|
||||
/* Close the locale archive. */
|
||||
extern void close_archive (struct locarhandle *ah);
|
||||
|
||||
/* Add given locale data to the archive. */
|
||||
extern int add_locale_to_archive (struct locarhandle *ah, const char *name,
|
||||
locale_data_t data, bool replace);
|
||||
|
||||
extern void add_alias (struct locarhandle *ah, const char *alias,
|
||||
bool replace, const char *oldname,
|
||||
uint32_t *locrec_offset_p);
|
||||
|
||||
extern struct namehashent *
|
||||
insert_name (struct locarhandle *ah,
|
||||
const char *name, size_t name_len, bool replace);
|
||||
|
||||
struct nameent
|
||||
{
|
||||
char *name;
|
||||
struct locrecent *locrec;
|
||||
};
|
||||
|
||||
struct dataent
|
||||
{
|
||||
const unsigned char *sum;
|
||||
uint32_t file_offset;
|
||||
};
|
||||
|
||||
static int
|
||||
nameentcmp (const void *a, const void *b)
|
||||
{
|
||||
struct locrecent *la = ((const struct nameent *) a)->locrec;
|
||||
struct locrecent *lb = ((const struct nameent *) b)->locrec;
|
||||
uint32_t start_a = -1, end_a = 0;
|
||||
uint32_t start_b = -1, end_b = 0;
|
||||
int cnt;
|
||||
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
if (la->record[cnt].offset < start_a)
|
||||
start_a = la->record[cnt].offset;
|
||||
if (la->record[cnt].offset + la->record[cnt].len > end_a)
|
||||
end_a = la->record[cnt].offset + la->record[cnt].len;
|
||||
}
|
||||
assert (start_a != (uint32_t)-1);
|
||||
assert (end_a != 0);
|
||||
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
if (lb->record[cnt].offset < start_b)
|
||||
start_b = lb->record[cnt].offset;
|
||||
if (lb->record[cnt].offset + lb->record[cnt].len > end_b)
|
||||
end_b = lb->record[cnt].offset + lb->record[cnt].len;
|
||||
}
|
||||
assert (start_b != (uint32_t)-1);
|
||||
assert (end_b != 0);
|
||||
|
||||
if (start_a != start_b)
|
||||
return (int)start_a - (int)start_b;
|
||||
return (int)end_a - (int)end_b;
|
||||
}
|
||||
|
||||
static int
|
||||
dataentcmp (const void *a, const void *b)
|
||||
{
|
||||
if (((const struct dataent *) a)->file_offset
|
||||
< ((const struct dataent *) b)->file_offset)
|
||||
return -1;
|
||||
|
||||
if (((const struct dataent *) a)->file_offset
|
||||
> ((const struct dataent *) b)->file_offset)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sumsearchfn (const void *key, const void *ent)
|
||||
{
|
||||
uint32_t keyn = *(uint32_t *)key;
|
||||
uint32_t entn = ((struct dataent *)ent)->file_offset;
|
||||
|
||||
if (keyn < entn)
|
||||
return -1;
|
||||
if (keyn > entn)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused,
|
||||
struct dataent *files, locale_data_t data)
|
||||
{
|
||||
int cnt;
|
||||
struct locrecent *locrec = name->locrec;
|
||||
struct dataent *file;
|
||||
data[LC_ALL].addr = ((char *) ah->addr) + locrec->record[LC_ALL].offset;
|
||||
data[LC_ALL].size = locrec->record[LC_ALL].len;
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
data[cnt].addr = ((char *) ah->addr) + locrec->record[cnt].offset;
|
||||
data[cnt].size = locrec->record[cnt].len;
|
||||
if (data[cnt].addr >= data[LC_ALL].addr
|
||||
&& data[cnt].addr + data[cnt].size
|
||||
<= data[LC_ALL].addr + data[LC_ALL].size)
|
||||
__md5_buffer (data[cnt].addr, data[cnt].size, data[cnt].sum);
|
||||
else
|
||||
{
|
||||
file = bsearch (&locrec->record[cnt].offset, files, sumused,
|
||||
sizeof (*files), sumsearchfn);
|
||||
if (file == NULL)
|
||||
error (EXIT_FAILURE, 0, "inconsistent template file");
|
||||
memcpy (data[cnt].sum, file->sum, sizeof (data[cnt].sum));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
fill_archive (struct locarhandle *tmpl_ah,
|
||||
const char *fname,
|
||||
size_t install_langs_count, char *install_langs_list[],
|
||||
size_t nlist, char *list[],
|
||||
const char *primary)
|
||||
{
|
||||
struct locarhandle ah;
|
||||
struct locarhead *head;
|
||||
int result = 0;
|
||||
struct nameent *names;
|
||||
struct namehashent *namehashtab;
|
||||
size_t cnt, used;
|
||||
struct dataent *files;
|
||||
struct sumhashent *sumhashtab;
|
||||
size_t sumused;
|
||||
struct locrecent *primary_locrec = NULL;
|
||||
struct nameent *primary_nameent = NULL;
|
||||
|
||||
head = tmpl_ah->addr;
|
||||
names = (struct nameent *) malloc (head->namehash_used
|
||||
* sizeof (struct nameent));
|
||||
files = (struct dataent *) malloc (head->sumhash_used
|
||||
* sizeof (struct dataent));
|
||||
if (names == NULL || files == NULL)
|
||||
error (EXIT_FAILURE, errno, "could not allocate tables");
|
||||
|
||||
namehashtab = (struct namehashent *) ((char *) tmpl_ah->addr
|
||||
+ head->namehash_offset);
|
||||
sumhashtab = (struct sumhashent *) ((char *) tmpl_ah->addr
|
||||
+ head->sumhash_offset);
|
||||
|
||||
for (cnt = used = 0; cnt < head->namehash_size; ++cnt)
|
||||
if (namehashtab[cnt].locrec_offset != 0)
|
||||
{
|
||||
char * name;
|
||||
int i;
|
||||
assert (used < head->namehash_used);
|
||||
name = tmpl_ah->addr + namehashtab[cnt].name_offset;
|
||||
if (install_langs_count == 0)
|
||||
{
|
||||
/* Always intstall the entry. */
|
||||
names[used].name = name;
|
||||
names[used++].locrec
|
||||
= (struct locrecent *) ((char *) tmpl_ah->addr +
|
||||
namehashtab[cnt].locrec_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only install the entry if the user asked for it via
|
||||
--install-langs. */
|
||||
for (i = 0; i < install_langs_count; i++)
|
||||
{
|
||||
/* Add one for "_" and one for the null terminator. */
|
||||
size_t len = strlen (install_langs_list[i]) + 2;
|
||||
char *install_lang = (char *)xmalloc (len);
|
||||
strcpy (install_lang, install_langs_list[i]);
|
||||
if (strchr (install_lang, '_') == NULL)
|
||||
strcat (install_lang, "_");
|
||||
if (strncmp (name, install_lang, strlen (install_lang)) == 0)
|
||||
{
|
||||
names[used].name = name;
|
||||
names[used++].locrec
|
||||
= (struct locrecent *) ((char *)tmpl_ah->addr
|
||||
+ namehashtab[cnt].locrec_offset);
|
||||
}
|
||||
free (install_lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort the names. */
|
||||
qsort (names, used, sizeof (struct nameent), nameentcmp);
|
||||
|
||||
for (cnt = sumused = 0; cnt < head->sumhash_size; ++cnt)
|
||||
if (sumhashtab[cnt].file_offset != 0)
|
||||
{
|
||||
assert (sumused < head->sumhash_used);
|
||||
files[sumused].sum = (const unsigned char *) sumhashtab[cnt].sum;
|
||||
files[sumused++].file_offset = sumhashtab[cnt].file_offset;
|
||||
}
|
||||
|
||||
/* Sort by file locations. */
|
||||
qsort (files, sumused, sizeof (struct dataent), dataentcmp);
|
||||
|
||||
/* Open the archive. This call never returns if we cannot
|
||||
successfully open the archive. */
|
||||
ah.fname = NULL;
|
||||
if (fname != NULL)
|
||||
ah.fname = fname;
|
||||
open_archive (&ah, false);
|
||||
|
||||
if (primary != NULL)
|
||||
{
|
||||
for (cnt = 0; cnt < used; ++cnt)
|
||||
if (strcmp (names[cnt].name, primary) == 0)
|
||||
break;
|
||||
if (cnt < used)
|
||||
{
|
||||
locale_data_t data;
|
||||
|
||||
compute_data (tmpl_ah, &names[cnt], sumused, files, data);
|
||||
result |= add_locale_to_archive (&ah, primary, data, 0);
|
||||
primary_locrec = names[cnt].locrec;
|
||||
primary_nameent = &names[cnt];
|
||||
}
|
||||
}
|
||||
|
||||
for (cnt = 0; cnt < used; ++cnt)
|
||||
if (&names[cnt] == primary_nameent)
|
||||
continue;
|
||||
else if ((cnt > 0 && names[cnt - 1].locrec == names[cnt].locrec)
|
||||
|| names[cnt].locrec == primary_locrec)
|
||||
{
|
||||
const char *oldname;
|
||||
struct namehashent *namehashent;
|
||||
uint32_t locrec_offset;
|
||||
|
||||
if (names[cnt].locrec == primary_locrec)
|
||||
oldname = primary;
|
||||
else
|
||||
oldname = names[cnt - 1].name;
|
||||
namehashent = insert_name (&ah, oldname, strlen (oldname), true);
|
||||
assert (namehashent->name_offset != 0);
|
||||
assert (namehashent->locrec_offset != 0);
|
||||
locrec_offset = namehashent->locrec_offset;
|
||||
add_alias (&ah, names[cnt].name, 0, oldname, &locrec_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
locale_data_t data;
|
||||
|
||||
compute_data (tmpl_ah, &names[cnt], sumused, files, data);
|
||||
result |= add_locale_to_archive (&ah, names[cnt].name, data, 0);
|
||||
}
|
||||
|
||||
while (nlist-- > 0)
|
||||
{
|
||||
const char *fname = *list++;
|
||||
size_t fnamelen = strlen (fname);
|
||||
struct stat64 st;
|
||||
DIR *dirp;
|
||||
struct dirent64 *d;
|
||||
int seen;
|
||||
locale_data_t data;
|
||||
int cnt;
|
||||
|
||||
/* First see whether this really is a directory and whether it
|
||||
contains all the require locale category files. */
|
||||
if (stat64 (fname, &st) < 0)
|
||||
{
|
||||
error (0, 0, "stat of \"%s\" failed: %s: ignored", fname,
|
||||
strerror (errno));
|
||||
continue;
|
||||
}
|
||||
if (!S_ISDIR (st.st_mode))
|
||||
{
|
||||
error (0, 0, "\"%s\" is no directory; ignored", fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
dirp = opendir (fname);
|
||||
if (dirp == NULL)
|
||||
{
|
||||
error (0, 0, "cannot open directory \"%s\": %s: ignored",
|
||||
fname, strerror (errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
seen = 0;
|
||||
while ((d = readdir64 (dirp)) != NULL)
|
||||
{
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
if (strcmp (d->d_name, locnames[cnt]) == 0)
|
||||
{
|
||||
unsigned char d_type;
|
||||
|
||||
/* We have an object of the required name. If it's
|
||||
a directory we have to look at a file with the
|
||||
prefix "SYS_". Otherwise we have found what we
|
||||
are looking for. */
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
d_type = d->d_type;
|
||||
|
||||
if (d_type != DT_REG)
|
||||
#endif
|
||||
{
|
||||
char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
if (d_type == DT_UNKNOWN)
|
||||
#endif
|
||||
{
|
||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"),
|
||||
d->d_name);
|
||||
|
||||
if (stat64 (fullname, &st) == -1)
|
||||
/* We cannot stat the file, ignore it. */
|
||||
break;
|
||||
|
||||
d_type = IFTODT (st.st_mode);
|
||||
}
|
||||
|
||||
if (d_type == DT_DIR)
|
||||
{
|
||||
/* We have to do more tests. The file is a
|
||||
directory and it therefore must contain a
|
||||
regular file with the same name except a
|
||||
"SYS_" prefix. */
|
||||
char *t = stpcpy (stpcpy (fullname, fname), "/");
|
||||
strcpy (stpcpy (stpcpy (t, d->d_name), "/SYS_"),
|
||||
d->d_name);
|
||||
|
||||
if (stat64 (fullname, &st) == -1)
|
||||
/* There is no SYS_* file or we cannot
|
||||
access it. */
|
||||
break;
|
||||
|
||||
d_type = IFTODT (st.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we found a regular file (eventually after
|
||||
following a symlink) we are successful. */
|
||||
if (d_type == DT_REG)
|
||||
++seen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir (dirp);
|
||||
|
||||
if (seen != __LC_LAST - 1)
|
||||
{
|
||||
/* We don't have all locale category files. Ignore the name. */
|
||||
error (0, 0, "incomplete set of locale files in \"%s\"",
|
||||
fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add the files to the archive. To do this we first compute
|
||||
sizes and the MD5 sums of all the files. */
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7];
|
||||
int fd;
|
||||
|
||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"), locnames[cnt]);
|
||||
fd = open64 (fullname, O_RDONLY);
|
||||
if (fd == -1 || fstat64 (fd, &st) == -1)
|
||||
{
|
||||
/* Cannot read the file. */
|
||||
if (fd != -1)
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (S_ISDIR (st.st_mode))
|
||||
{
|
||||
char *t;
|
||||
close (fd);
|
||||
t = stpcpy (stpcpy (fullname, fname), "/");
|
||||
strcpy (stpcpy (stpcpy (t, locnames[cnt]), "/SYS_"),
|
||||
locnames[cnt]);
|
||||
|
||||
fd = open64 (fullname, O_RDONLY);
|
||||
if (fd == -1 || fstat64 (fd, &st) == -1
|
||||
|| !S_ISREG (st.st_mode))
|
||||
{
|
||||
if (fd != -1)
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Map the file. */
|
||||
data[cnt].addr = mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED,
|
||||
fd, 0);
|
||||
if (data[cnt].addr == MAP_FAILED)
|
||||
{
|
||||
/* Cannot map it. */
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
|
||||
data[cnt].size = st.st_size;
|
||||
__md5_buffer (data[cnt].addr, st.st_size, data[cnt].sum);
|
||||
|
||||
/* We don't need the file descriptor anymore. */
|
||||
close (fd);
|
||||
}
|
||||
|
||||
if (cnt != __LC_LAST)
|
||||
{
|
||||
while (cnt-- > 0)
|
||||
if (cnt != LC_ALL)
|
||||
munmap (data[cnt].addr, data[cnt].size);
|
||||
|
||||
error (0, 0, "cannot read all files in \"%s\": ignored", fname);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
result |= add_locale_to_archive (&ah, basename (fname), data, 0);
|
||||
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
munmap (data[cnt].addr, data[cnt].size);
|
||||
}
|
||||
|
||||
/* We are done. */
|
||||
close_archive (&ah);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf ("\
|
||||
Usage: build-locale-archive [OPTION]... [TEMPLATE-FILE] [ARCHIVE-FILE]\n\
|
||||
Builds a locale archive from a template file.\n\
|
||||
Options:\n\
|
||||
-h, --help Print this usage message.\n\
|
||||
-v, --verbose Verbose execution.\n\
|
||||
-l, --install-langs=LIST Only include locales given in LIST into the \n\
|
||||
locale archive. LIST is a colon separated list\n\
|
||||
of locale prefixes, for example \"de:en:ja\".\n\
|
||||
The special argument \"all\" means to install\n\
|
||||
all languages and it must be present by itself.\n\
|
||||
If \"all\" is present with any other language it\n\
|
||||
will be treated as the name of a locale.\n\
|
||||
If the --install-langs option is missing, all\n\
|
||||
locales are installed. The colon separated list\n\
|
||||
can contain any strings matching the beginning of\n\
|
||||
locale names.\n\
|
||||
If a string does not contain a \"_\", it is added.\n\
|
||||
Examples:\n\
|
||||
--install-langs=\"en\"\n\
|
||||
installs en_US, en_US.iso88591,\n\
|
||||
en_US.iso885915, en_US.utf8,\n\
|
||||
en_GB ...\n\
|
||||
--install-langs=\"en_US.utf8\"\n\
|
||||
installs only en_US.utf8.\n\
|
||||
--install-langs=\"ko\"\n\
|
||||
installs ko_KR, ko_KR.euckr,\n\
|
||||
ko_KR.utf8 but *not* kok_IN\n\
|
||||
because \"ko\" does not contain\n\
|
||||
\"_\" and it is silently added\n\
|
||||
--install-langs\"ko:kok\"\n\
|
||||
installs ko_KR, ko_KR.euckr,\n\
|
||||
ko_KR.utf8, kok_IN, and\n\
|
||||
kok_IN.utf8.\n\
|
||||
--install-langs=\"POSIX\" will\n\
|
||||
installs *no* locales at all\n\
|
||||
because POSIX matches none of\n\
|
||||
the locales. Actually, any string\n\
|
||||
matching nothing will do that.\n\
|
||||
POSIX and C will always be\n\
|
||||
available because they are\n\
|
||||
builtin.\n\
|
||||
Aliases are installed as well,\n\
|
||||
i.e. --install-langs=\"de\"\n\
|
||||
will install not only every locale starting with\n\
|
||||
\"de\" but also the aliases \"deutsch\"\n\
|
||||
and and \"german\" although the latter does not\n\
|
||||
start with \"de\".\n\
|
||||
\n\
|
||||
If the arguments TEMPLATE-FILE and ARCHIVE-FILE are not given the locations\n\
|
||||
where the glibc used expects these files are used by default.\n\
|
||||
");
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
char path[4096];
|
||||
DIR *dirp;
|
||||
struct dirent64 *d;
|
||||
struct stat64 st;
|
||||
char *list[16384], *primary;
|
||||
char *lang;
|
||||
int install_langs_count = 0;
|
||||
int i;
|
||||
char *install_langs_arg, *ila_start;
|
||||
char **install_langs_list;
|
||||
unsigned int cnt = 0;
|
||||
struct locarhandle tmpl_ah;
|
||||
char *new_locar_fname = NULL;
|
||||
size_t loc_path_len = strlen (loc_path);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int c;
|
||||
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"install-langs", required_argument, 0, 'l'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
/* getopt_long stores the option index here. */
|
||||
int option_index = 0;
|
||||
|
||||
c = getopt_long (argc, argv, "vhl:",
|
||||
long_options, &option_index);
|
||||
|
||||
/* Detect the end of the options. */
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("unknown option %s", long_options[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
usage ();
|
||||
exit (1);
|
||||
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
be_quiet = 0;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage ();
|
||||
exit (0);
|
||||
|
||||
case 'l':
|
||||
install_langs_arg = ila_start = strdup (optarg);
|
||||
/* If the argument to --install-lang is "all", do
|
||||
not limit the list of languages to install and install
|
||||
them all. We do not support installing a single locale
|
||||
called "all". */
|
||||
#define MAGIC_INSTALL_ALL "all"
|
||||
if (install_langs_arg != NULL
|
||||
&& install_langs_arg[0] != '\0'
|
||||
&& !(strncmp(install_langs_arg, MAGIC_INSTALL_ALL,
|
||||
strlen(MAGIC_INSTALL_ALL)) == 0
|
||||
&& strlen (install_langs_arg) == 3))
|
||||
{
|
||||
/* Count the number of languages we will install. */
|
||||
while (true)
|
||||
{
|
||||
lang = strtok(install_langs_arg, ":;,");
|
||||
if (lang == NULL)
|
||||
break;
|
||||
install_langs_count++;
|
||||
install_langs_arg = NULL;
|
||||
}
|
||||
free (ila_start);
|
||||
/* Copy the list. */
|
||||
install_langs_list = (char **)xmalloc (sizeof(char *) * install_langs_count);
|
||||
install_langs_arg = ila_start = strdup (optarg);
|
||||
install_langs_count = 0;
|
||||
while (true)
|
||||
{
|
||||
lang = strtok(install_langs_arg, ":;,");
|
||||
if (lang == NULL)
|
||||
break;
|
||||
install_langs_list[install_langs_count] = lang;
|
||||
install_langs_count++;
|
||||
install_langs_arg = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
/* getopt_long already printed an error message. */
|
||||
usage ();
|
||||
exit (0);
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
tmpl_ah.fname = NULL;
|
||||
if (optind < argc)
|
||||
tmpl_ah.fname = argv[optind];
|
||||
if (optind + 1 < argc)
|
||||
new_locar_fname = argv[optind + 1];
|
||||
if (verbose)
|
||||
{
|
||||
if (tmpl_ah.fname)
|
||||
printf("input archive file specified on command line: %s\n",
|
||||
tmpl_ah.fname);
|
||||
else
|
||||
printf("using default input archive file.\n");
|
||||
if (new_locar_fname)
|
||||
printf("output archive file specified on command line: %s\n",
|
||||
new_locar_fname);
|
||||
else
|
||||
printf("using default output archive file.\n");
|
||||
}
|
||||
|
||||
dirp = opendir (loc_path);
|
||||
if (dirp == NULL)
|
||||
error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path);
|
||||
|
||||
open_tmpl_archive (&tmpl_ah);
|
||||
|
||||
if (new_locar_fname)
|
||||
unlink (new_locar_fname);
|
||||
else
|
||||
unlink (locar_file);
|
||||
primary = getenv ("LC_ALL");
|
||||
if (primary == NULL)
|
||||
primary = getenv ("LANG");
|
||||
if (primary != NULL)
|
||||
{
|
||||
if (strncmp (primary, "ja", 2) != 0
|
||||
&& strncmp (primary, "ko", 2) != 0
|
||||
&& strncmp (primary, "zh", 2) != 0)
|
||||
{
|
||||
char *ptr = malloc (strlen (primary) + strlen (".utf8") + 1), *p, *q;
|
||||
/* This leads to invalid locales sometimes:
|
||||
de_DE.iso885915@euro -> de_DE.utf8@euro */
|
||||
if (ptr != NULL)
|
||||
{
|
||||
p = ptr;
|
||||
q = primary;
|
||||
while (*q && *q != '.' && *q != '@')
|
||||
*p++ = *q++;
|
||||
if (*q == '.')
|
||||
while (*q && *q != '@')
|
||||
q++;
|
||||
p = stpcpy (p, ".utf8");
|
||||
strcpy (p, q);
|
||||
primary = ptr;
|
||||
}
|
||||
else
|
||||
primary = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (path, loc_path, loc_path_len);
|
||||
|
||||
while ((d = readdir64 (dirp)) != NULL)
|
||||
{
|
||||
if (strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0)
|
||||
continue;
|
||||
if (strchr (d->d_name, '_') == NULL)
|
||||
continue;
|
||||
|
||||
size_t d_name_len = strlen (d->d_name);
|
||||
if (loc_path_len + d_name_len + 1 > sizeof (path))
|
||||
{
|
||||
error (0, 0, "too long filename \"%s\"", d->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy (path + loc_path_len, d->d_name, d_name_len + 1);
|
||||
if (stat64 (path, &st) < 0)
|
||||
{
|
||||
error (0, errno, "cannot stat \"%s\"", path);
|
||||
continue;
|
||||
}
|
||||
if (! S_ISDIR (st.st_mode))
|
||||
continue;
|
||||
if (cnt == 16384)
|
||||
{
|
||||
error (0, 0, "too many directories in \"%s\"", loc_path);
|
||||
break;
|
||||
}
|
||||
list[cnt] = strdup (path);
|
||||
if (list[cnt] == NULL)
|
||||
{
|
||||
error (0, errno, "cannot add file to list \"%s\"", path);
|
||||
continue;
|
||||
}
|
||||
if (primary != NULL && cnt > 0 && strcmp (primary, d->d_name) == 0)
|
||||
{
|
||||
char *p = list[0];
|
||||
list[0] = list[cnt];
|
||||
list[cnt] = p;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
closedir (dirp);
|
||||
/* Store the archive to the file specified as the second argument on the
|
||||
command line or the default locale archive. */
|
||||
fill_archive (&tmpl_ah, new_locar_fname,
|
||||
install_langs_count, install_langs_list,
|
||||
cnt, list, primary);
|
||||
close_archive (&tmpl_ah);
|
||||
truncate (tmpl_file, 0);
|
||||
if (install_langs_count > 0)
|
||||
{
|
||||
free (ila_start);
|
||||
free (install_langs_list);
|
||||
}
|
||||
char *tz_argv[] = { "/usr/sbin/tzdata-update", NULL };
|
||||
execve (tz_argv[0], (char *const *)tz_argv, (char *const *)&tz_argv[1]);
|
||||
exit (0);
|
||||
}
|
@ -5,10 +5,30 @@ component="glibc"
|
||||
rm -f series.new
|
||||
extra_args="--fuzz=0"
|
||||
count=0
|
||||
# Transform patches into series file.
|
||||
grep '^Patch.*:' glibc.spec | sed -e 's,Patch.*: ,,g' > series.new
|
||||
count=`wc -l series.new | sed -e 's, .*$,,g'`
|
||||
# Filter out the patches, and use `_` as our pseudo-IFS to prevent expansion.
|
||||
for i in `grep '^%patch' glibc.spec | sed -e 's,%patch,,g' -e 's, ,_,g'`; do
|
||||
# Split the patch into number and arguments.
|
||||
# 1 - Patch number.
|
||||
# 2-N - Patch arguments.
|
||||
# Get back our elements by undoing pseudo-IFS change.
|
||||
elements=(`echo $i | sed -e 's,_, ,g'`)
|
||||
num=${elements[0]}
|
||||
args=${elements[@]:1}
|
||||
# Find the next patch that applies in order and write it out.
|
||||
# This way we transform the patch # list into a patch file list in order.
|
||||
grep "Patch${num}: " glibc.spec \
|
||||
| sed -e 's,Patch.*: ,,g' -e "s,\$, ${args[@]} ${extra_args},g" \
|
||||
| sed -e "s,%{name},${component},g" \
|
||||
>> series.new
|
||||
((count++))
|
||||
done
|
||||
# Double check we processed the correct number of patches.
|
||||
fcount=`wc -l series.new | sed -e 's, .*$,,g'`
|
||||
if [ $fcount -ne $count ]; then
|
||||
echo "Error! Processed patch count doesn't match spec file count ($fcount != $count)."
|
||||
exit 1
|
||||
fi
|
||||
echo "Processed $count patches."
|
||||
mv series.new series
|
||||
echo "Generated quilt ./series file. Please do not commit."
|
||||
echo "Generated quilt ./series file, please commit."
|
||||
exit 0
|
||||
|
13
glibc-aarch64-tls-fixes.patch
Normal file
13
glibc-aarch64-tls-fixes.patch
Normal file
@ -0,0 +1,13 @@
|
||||
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
|
||||
index 997c860..50b37b0 100644
|
||||
--- a/sysdeps/aarch64/dl-machine.h
|
||||
+++ b/sysdeps/aarch64/dl-machine.h
|
||||
@@ -295,7 +295,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
|
||||
# ifndef SHARED
|
||||
CHECK_STATIC_TLS (map, sym_map);
|
||||
# else
|
||||
- if (!TRY_STATIC_TLS (map, sym_map))
|
||||
+ if (1)
|
||||
{
|
||||
td->arg = _dl_make_tlsdesc_dynamic
|
||||
(sym_map, sym->st_value + reloc->r_addend);
|
33
glibc-aarch64-workaround-nzcv-clobber-in-tlsdesc.patch
Normal file
33
glibc-aarch64-workaround-nzcv-clobber-in-tlsdesc.patch
Normal file
@ -0,0 +1,33 @@
|
||||
diff --git a/sysdeps/aarch64/dl-tlsdesc.S b/sysdeps/aarch64/dl-tlsdesc.S
|
||||
index ded5471..7d28496 100644
|
||||
--- a/sysdeps/aarch64/dl-tlsdesc.S
|
||||
+++ b/sysdeps/aarch64/dl-tlsdesc.S
|
||||
@@ -140,7 +140,7 @@ _dl_tlsdesc_undefweak:
|
||||
cfi_startproc
|
||||
.align 2
|
||||
_dl_tlsdesc_dynamic:
|
||||
-# define NSAVEXREGPAIRS 2
|
||||
+# define NSAVEXREGPAIRS 3
|
||||
stp x29, x30, [sp,#-(32+16*NSAVEXREGPAIRS)]!
|
||||
cfi_adjust_cfa_offset (32+16*NSAVEXREGPAIRS)
|
||||
mov x29, sp
|
||||
@@ -151,6 +151,10 @@ _dl_tlsdesc_dynamic:
|
||||
stp x1, x2, [sp, #32+16*0]
|
||||
stp x3, x4, [sp, #32+16*1]
|
||||
|
||||
+ /* Work around GCC rescheduling compares across tlsdesc calls. */
|
||||
+ mrs x30, nzcv
|
||||
+ stp xzr, x30, [sp, #32+16*2]
|
||||
+
|
||||
mrs x4, tpidr_el0
|
||||
/* The ldar here happens after the load from [x0] at the call site
|
||||
(that is generated by the compiler as part of the TLS access ABI),
|
||||
@@ -169,6 +173,8 @@ _dl_tlsdesc_dynamic:
|
||||
1:
|
||||
ldp x1, x2, [sp, #32+16*0]
|
||||
ldp x3, x4, [sp, #32+16*1]
|
||||
+ ldp xzr, x30, [sp, #32+16*2]
|
||||
+ msr nzcv, x30
|
||||
|
||||
ldp x29, x30, [sp], #(32+16*NSAVEXREGPAIRS)
|
||||
cfi_adjust_cfa_offset (-32-16*NSAVEXREGPAIRS)
|
20
glibc-arm-hardfloat-3.patch
Normal file
20
glibc-arm-hardfloat-3.patch
Normal file
@ -0,0 +1,20 @@
|
||||
diff -Nrup a/elf/dl-load.c b/elf/dl-load.c
|
||||
--- a/elf/dl-load.c 2012-06-06 13:07:41.727524312 -0600
|
||||
+++ b/elf/dl-load.c 2012-06-06 13:11:19.308681002 -0600
|
||||
@@ -2093,10 +2093,14 @@ _dl_map_object (struct link_map *loader,
|
||||
soname = ((const char *) D_PTR (l, l_info[DT_STRTAB])
|
||||
+ l->l_info[DT_SONAME]->d_un.d_val);
|
||||
if (strcmp (name, soname) != 0)
|
||||
- continue;
|
||||
+#ifdef __arm__
|
||||
+ if (strcmp (name, "ld-linux.so.3")
|
||||
+ || strcmp (soname, "ld-linux-armhf.so.3"))
|
||||
+#endif
|
||||
+ continue;
|
||||
|
||||
/* We have a match on a new name -- cache it. */
|
||||
- add_name_to_object (l, soname);
|
||||
+ add_name_to_object (l, name);
|
||||
l->l_soname_added = 1;
|
||||
}
|
||||
|
41
glibc-bench-build.patch
Normal file
41
glibc-bench-build.patch
Normal file
@ -0,0 +1,41 @@
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index 710ce7e..3fe9e73 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -12,7 +12,7 @@ install:
|
||||
LC_ALL=C; export LC_ALL; \
|
||||
$(MAKE) -r PARALLELMFLAGS="$(PARALLELMFLAGS)" -C $(srcdir) objdir=`pwd` $@
|
||||
|
||||
-bench bench-clean:
|
||||
+bench bench-clean bench-build:
|
||||
$(MAKE) -C $(srcdir)/benchtests $(PARALLELMFLAGS) objdir=`pwd` $@
|
||||
|
||||
# Convenience target to rebuild ULPs for all math tests.
|
||||
diff --git a/Rules b/Rules
|
||||
index 4f9cdf3..42d0368 100644
|
||||
--- a/Rules
|
||||
+++ b/Rules
|
||||
@@ -83,7 +83,7 @@ common-generated += dummy.o dummy.c
|
||||
|
||||
# This makes all the auxiliary and test programs.
|
||||
|
||||
-.PHONY: others tests bench
|
||||
+.PHONY: others tests bench bench-build
|
||||
|
||||
ifeq ($(build-programs),yes)
|
||||
others: $(addprefix $(objpfx),$(others) $(sysdep-others) $(extra-objs))
|
||||
diff --git a/benchtests/Makefile b/benchtests/Makefile
|
||||
index fd3036d..7cbceaa 100644
|
||||
--- a/benchtests/Makefile
|
||||
+++ b/benchtests/Makefile
|
||||
@@ -103,6 +103,10 @@ bench-clean:
|
||||
|
||||
bench: $(timing-type) $(gen-locales) bench-set bench-func bench-malloc
|
||||
|
||||
+bench-build: bench-set-build bench-func-build
|
||||
+bench-set-build: $(binaries-benchset)
|
||||
+bench-func-build: $(binaries-bench) $(binaries-bench-malloc)
|
||||
+
|
||||
bench-set: $(binaries-benchset)
|
||||
for run in $^; do \
|
||||
echo "Running $${run}"; \
|
140
glibc-bug-regex-gcc5.patch
Normal file
140
glibc-bug-regex-gcc5.patch
Normal file
@ -0,0 +1,140 @@
|
||||
Index: glibc-2.22-193-g315267a/posix/bug-regex11.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/posix/bug-regex11.c
|
||||
+++ glibc-2.22-193-g315267a/posix/bug-regex11.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
/* Tests supposed to match. */
|
||||
struct
|
||||
@@ -119,6 +120,14 @@ main (void)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since n is limited to
|
||||
+ static nmatch which is limited to at most 5 (see tests above).
|
||||
+ This is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (n = 0; n < tests[i].nmatch; ++n)
|
||||
if (rm[n].rm_so != tests[i].rm[n].rm_so
|
||||
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
|
||||
@@ -130,6 +139,7 @@ main (void)
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
regfree (&re);
|
||||
}
|
||||
Index: glibc-2.22-193-g315267a/posix/bug-regex17.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/posix/bug-regex17.c
|
||||
+++ glibc-2.22-193-g315267a/posix/bug-regex17.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
/* Tests supposed to match. */
|
||||
struct
|
||||
@@ -87,6 +88,14 @@ do_test (void)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since n is limited to
|
||||
+ static nmatch which is limited to at most 5 (see tests above).
|
||||
+ This is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (n = 0; n < tests[i].nmatch; ++n)
|
||||
if (rm[n].rm_so != tests[i].rm[n].rm_so
|
||||
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
|
||||
@@ -98,6 +107,7 @@ do_test (void)
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
regfree (&re);
|
||||
}
|
||||
Index: glibc-2.22-193-g315267a/posix/bug-regex18.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/posix/bug-regex18.c
|
||||
+++ glibc-2.22-193-g315267a/posix/bug-regex18.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
/* Tests supposed to match. */
|
||||
struct
|
||||
@@ -80,6 +81,14 @@ main (void)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since n is limited to
|
||||
+ static nmatch which is limited to at most 5 (see tests above).
|
||||
+ This is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (n = 0; n < tests[i].nmatch; ++n)
|
||||
if (rm[n].rm_so != tests[i].rm[n].rm_so
|
||||
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
|
||||
@@ -91,6 +100,7 @@ main (void)
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
regfree (&re);
|
||||
}
|
||||
Index: glibc-2.22-193-g315267a/posix/bug-regex30.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/posix/bug-regex30.c
|
||||
+++ glibc-2.22-193-g315267a/posix/bug-regex30.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
/* Tests supposed to match. */
|
||||
struct
|
||||
@@ -80,6 +81,14 @@ do_test (void)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since n is limited to
|
||||
+ static nmatch which is limited to at most 5 (see tests above).
|
||||
+ This is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (n = 0; n < tests[i].nmatch; ++n)
|
||||
if (rm[n].rm_so != tests[i].rm[n].rm_so
|
||||
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
|
||||
@@ -91,6 +100,7 @@ do_test (void)
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
regfree (&re);
|
||||
}
|
@ -1,19 +1,3 @@
|
||||
Short description: Add C.UTF-8 support.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-submitted
|
||||
|
||||
This patch needs to upstream as part of Carlos O'Donell
|
||||
<carlos@redhat.com>'s work on enabling upstream C.UTF-8 support. This
|
||||
work is currently blocked on cleaning up the test results to prove that
|
||||
full code-point sorting is working as intended.
|
||||
|
||||
Note that this patch does not provide full code-point sorting as
|
||||
expected.
|
||||
|
||||
This patch needs to upstream as soon as possible since it would be nice
|
||||
to have this in F29 and fixed.
|
||||
|
||||
From 2eda7b462b415105f5a05c1323372d4e39d46439 Mon Sep 17 00:00:00 2001
|
||||
From: Mike FABIAN <mfabian@redhat.com>
|
||||
Date: Mon, 10 Aug 2015 15:58:12 +0200
|
||||
@ -60,18 +44,18 @@ index 0000000..fdf460e
|
||||
+revision "1.0"
|
||||
+date "2015-08-10"
|
||||
+%
|
||||
+category "i18n:2012";LC_IDENTIFICATION
|
||||
+category "i18n:2012";LC_CTYPE
|
||||
+category "i18n:2012";LC_COLLATE
|
||||
+category "i18n:2012";LC_TIME
|
||||
+category "i18n:2012";LC_NUMERIC
|
||||
+category "i18n:2012";LC_MONETARY
|
||||
+category "i18n:2012";LC_MESSAGES
|
||||
+category "i18n:2012";LC_PAPER
|
||||
+category "i18n:2012";LC_NAME
|
||||
+category "i18n:2012";LC_ADDRESS
|
||||
+category "i18n:2012";LC_TELEPHONE
|
||||
+category "i18n:2012";LC_MEASUREMENT
|
||||
+category "C:2015";LC_IDENTIFICATION
|
||||
+category "C:2015";LC_CTYPE
|
||||
+category "C:2015";LC_COLLATE
|
||||
+category "C:2015";LC_TIME
|
||||
+category "C:2015";LC_NUMERIC
|
||||
+category "C:2015";LC_MONETARY
|
||||
+category "C:2015";LC_MESSAGES
|
||||
+category "C:2015";LC_PAPER
|
||||
+category "C:2015";LC_NAME
|
||||
+category "C:2015";LC_ADDRESS
|
||||
+category "C:2015";LC_TELEPHONE
|
||||
+category "C:2015";LC_MEASUREMENT
|
||||
+END LC_IDENTIFICATION
|
||||
+
|
||||
+LC_CTYPE
|
||||
@ -88,21 +72,21 @@ index 0000000..fdf460e
|
||||
+<U0000>
|
||||
+..
|
||||
+<UFFFF>
|
||||
+<U00010000>
|
||||
+<U10000>
|
||||
+..
|
||||
+<U0001FFFF>
|
||||
+<U00020000>
|
||||
+<U1FFFF>
|
||||
+<U20000>
|
||||
+..
|
||||
+<U0002FFFF>
|
||||
+<U000E0000>
|
||||
+<U2FFFF>
|
||||
+<UE0000>
|
||||
+..
|
||||
+<U000EFFFF>
|
||||
+<U000F0000>
|
||||
+<UEFFFF>
|
||||
+<UF0000>
|
||||
+..
|
||||
+<U000FFFFF>
|
||||
+<U00100000>
|
||||
+<UFFFFF>
|
||||
+<U100000>
|
||||
+..
|
||||
+<U0010FFFF>
|
||||
+<U10FFFF>
|
||||
+UNDEFINED
|
||||
+order_end
|
||||
+END LC_COLLATE
|
||||
|
@ -1,12 +1,3 @@
|
||||
Short description: Adjust CS_PATH return value.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
In Fedora we should return only /usr/bin because /bin is just a symlink
|
||||
to /usr/bin after MoveToUsr transition (which glibc has not really
|
||||
completed).
|
||||
|
||||
diff -pruN a/sysdeps/unix/confstr.h b/sysdeps/unix/confstr.h
|
||||
--- a/sysdeps/unix/confstr.h 2012-12-25 08:32:13.000000000 +0530
|
||||
+++ b/sysdeps/unix/confstr.h 2014-09-05 20:02:55.698275219 +0530
|
||||
|
22
glibc-disable-rwlock-elision.patch
Normal file
22
glibc-disable-rwlock-elision.patch
Normal file
@ -0,0 +1,22 @@
|
||||
diff -urN glibc-2.20.mod/sysdeps/unix/sysv/linux/x86/elision-conf.c glibc-2.20/sysdeps/unix/sysv/linux/x86/elision-conf.c
|
||||
--- glibc-2.20.mod/sysdeps/unix/sysv/linux/x86/elision-conf.c 2014-09-27 00:25:46.443462345 -0400
|
||||
+++ glibc-2.20/sysdeps/unix/sysv/linux/x86/elision-conf.c 2014-09-27 00:29:53.586615813 -0400
|
||||
@@ -62,12 +62,16 @@
|
||||
char **argv __attribute__ ((unused)),
|
||||
char **environ)
|
||||
{
|
||||
- __elision_available = HAS_CPU_FEATURE (RTM);
|
||||
#ifdef ENABLE_LOCK_ELISION
|
||||
+ __elision_available = HAS_CPU_FEATURE (RTM);
|
||||
__pthread_force_elision = __libc_enable_secure ? 0 : __elision_available;
|
||||
-#endif
|
||||
if (!HAS_CPU_FEATURE (RTM))
|
||||
__elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks */
|
||||
+#else
|
||||
+ __elision_available = 0;
|
||||
+ __pthread_force_elision = 0;
|
||||
+ __elision_aconf.retry_try_xbegin = 0;
|
||||
+#endif
|
||||
}
|
||||
|
||||
#ifdef SHARED
|
32
glibc-dns-host-gcc5.patch
Normal file
32
glibc-dns-host-gcc5.patch
Normal file
@ -0,0 +1,32 @@
|
||||
Index: glibc-2.22-193-g315267a/resolv/nss_dns/dns-host.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/resolv/nss_dns/dns-host.c
|
||||
+++ glibc-2.22-193-g315267a/resolv/nss_dns/dns-host.c
|
||||
@@ -79,6 +79,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <sys/syslog.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
#include "nsswitch.h"
|
||||
|
||||
@@ -561,10 +562,19 @@ addrsort (char **ap, int num)
|
||||
num = MAX_NR_ADDRS;
|
||||
for (i = 0; i < num; i++, p++)
|
||||
{
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since i is limited to
|
||||
+ _res.nsort which is limited to MAXRESOLVSORT. This
|
||||
+ is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (j = 0 ; (unsigned)j < _res.nsort; j++)
|
||||
if (_res.sort_list[j].addr.s_addr ==
|
||||
(((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
|
||||
break;
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
aval[i] = j;
|
||||
if (needsort == 0 && i > 0 && j < aval[i-1])
|
||||
needsort = i;
|
@ -1,40 +1,30 @@
|
||||
Short description: Cleanup use of _dl_starting_up.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: https://sourceware.org/ml/libc-alpha/2014-02/msg00589.html
|
||||
|
||||
Upstream discussions:
|
||||
https://sourceware.org/ml/libc-alpha/2014-02/msg00580.html
|
||||
|
||||
Based on the following commit:
|
||||
~~~
|
||||
From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schwab <schwab@redhat.com>
|
||||
Date: Fri, 11 Jun 2010 11:04:11 +0200
|
||||
Subject: [PATCH] Properly set __libc_multiple_libcs
|
||||
|
||||
* elf/rtld.c (_dl_starting_up): Always define.
|
||||
(dl_main): Always set _dl_starting_up.
|
||||
* elf/dl-support.c (_dl_starting_up): Always define.
|
||||
* elf/dl-init.c (_dl_init): Always clear _dl_starting_up.
|
||||
|
||||
---
|
||||
ChangeLog | 7 +++++++
|
||||
elf/dl-init.c | 4 ----
|
||||
elf/dl-support.c | 2 --
|
||||
elf/rtld.c | 4 ----
|
||||
4 files changed, 7 insertions(+), 10 deletions(-)
|
||||
~~~
|
||||
|
||||
This patch needs to go upstream to get cleaned up, but has always involed
|
||||
analysis of the GNU/Hurd parts of the change and that stalled out, but
|
||||
perhaps with build-many-glibcs we can now test these changes more easily.
|
||||
|
||||
Index: b/elf/dl-init.c
|
||||
===================================================================
|
||||
--- a/elf/dl-init.c
|
||||
+++ b/elf/dl-init.c
|
||||
@@ -119,8 +119,6 @@ _dl_init (struct link_map *main_map, int
|
||||
#
|
||||
# Upstream discussions:
|
||||
# https://sourceware.org/ml/libc-alpha/2014-02/msg00580.html
|
||||
#
|
||||
# Based on the following commit:
|
||||
#
|
||||
# From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001
|
||||
# From: Andreas Schwab <schwab@redhat.com>
|
||||
# Date: Fri, 11 Jun 2010 11:04:11 +0200
|
||||
# Subject: [PATCH] Properly set __libc_multiple_libcs
|
||||
#
|
||||
# * elf/rtld.c (_dl_starting_up): Always define.
|
||||
# (dl_main): Always set _dl_starting_up.
|
||||
# * elf/dl-support.c (_dl_starting_up): Always define.
|
||||
# * elf/dl-init.c (_dl_init): Always clear _dl_starting_up.
|
||||
#
|
||||
# ---
|
||||
# ChangeLog | 7 +++++++
|
||||
# elf/dl-init.c | 4 ----
|
||||
# elf/dl-support.c | 2 --
|
||||
# elf/rtld.c | 4 ----
|
||||
# 4 files changed, 7 insertions(+), 10 deletions(-)
|
||||
#
|
||||
diff -urN glibc-2.20-205-ga39208b/elf/dl-init.c glibc-2.20-205-ga39208b.mod/elf/dl-init.c
|
||||
--- glibc-2.20-205-ga39208b/elf/dl-init.c 2014-11-21 16:08:32.744913590 -0500
|
||||
+++ glibc-2.20-205-ga39208b.mod/elf/dl-init.c 2014-11-21 16:09:42.485708197 -0500
|
||||
@@ -119,8 +119,6 @@
|
||||
while (i-- > 0)
|
||||
call_init (main_map->l_initfini[i], argc, argv, env);
|
||||
|
||||
@ -43,11 +33,10 @@ Index: b/elf/dl-init.c
|
||||
_dl_starting_up = 0;
|
||||
-#endif
|
||||
}
|
||||
Index: b/elf/dl-support.c
|
||||
===================================================================
|
||||
--- a/elf/dl-support.c
|
||||
+++ b/elf/dl-support.c
|
||||
@@ -117,10 +117,8 @@ struct r_scope_elem _dl_initial_searchli
|
||||
diff -urN glibc-2.20-205-ga39208b/elf/dl-support.c glibc-2.20-205-ga39208b.mod/elf/dl-support.c
|
||||
--- glibc-2.20-205-ga39208b/elf/dl-support.c 2014-11-19 14:35:03.000000000 -0500
|
||||
+++ glibc-2.20-205-ga39208b.mod/elf/dl-support.c 2014-11-21 16:09:54.829671843 -0500
|
||||
@@ -118,10 +118,8 @@
|
||||
.r_nlist = 1,
|
||||
};
|
||||
|
||||
@ -58,19 +47,18 @@ Index: b/elf/dl-support.c
|
||||
|
||||
/* Random data provided by the kernel. */
|
||||
void *_dl_random;
|
||||
Index: b/elf/rtld.c
|
||||
===================================================================
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -214,7 +214,6 @@ audit_list_iter_next (struct audit_list_
|
||||
return iter->previous->name;
|
||||
}
|
||||
diff -urN glibc-2.20-205-ga39208b/elf/rtld.c glibc-2.20-205-ga39208b.mod/elf/rtld.c
|
||||
--- glibc-2.20-205-ga39208b/elf/rtld.c 2014-11-21 16:08:32.745913587 -0500
|
||||
+++ glibc-2.20-205-ga39208b.mod/elf/rtld.c 2014-11-21 16:09:05.614816785 -0500
|
||||
@@ -107,7 +107,6 @@
|
||||
struct audit_list *next;
|
||||
} *audit_list;
|
||||
|
||||
-#ifndef HAVE_INLINED_SYSCALLS
|
||||
/* Set nonzero during loading and initialization of executable and
|
||||
libraries, cleared before the executable's entry point runs. This
|
||||
must not be initialized to nonzero, because the unused dynamic
|
||||
@@ -224,7 +223,6 @@ audit_list_iter_next (struct audit_list_
|
||||
@@ -117,7 +116,6 @@
|
||||
never be called. */
|
||||
int _dl_starting_up = 0;
|
||||
rtld_hidden_def (_dl_starting_up)
|
||||
@ -78,7 +66,7 @@ Index: b/elf/rtld.c
|
||||
|
||||
/* This is the structure which defines all variables global to ld.so
|
||||
(except those which cannot be added for some reason). */
|
||||
@@ -898,10 +896,8 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
@@ -776,10 +774,8 @@
|
||||
/* Process the environment variable which control the behaviour. */
|
||||
process_envvars (&mode);
|
||||
|
||||
|
101
glibc-fedora-elf-ORIGIN.patch
Normal file
101
glibc-fedora-elf-ORIGIN.patch
Normal file
@ -0,0 +1,101 @@
|
||||
From 207e77fd3f0a94acdf0557608dd4f10ce0e0f22f Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schwab <schwab@redhat.com>
|
||||
Date: Mon, 9 May 2011 10:55:58 +0200
|
||||
Subject: [PATCH] Never leave $ORIGIN unexpanded
|
||||
|
||||
* elf/dl-load.c (is_dst): Remove parameter secure, all callers
|
||||
changed. Move check for valid use of $ORIGIN ...
|
||||
(_dl_dst_substitute): ... here. Reset check_for_trusted when a
|
||||
path element is skipped.
|
||||
|
||||
---
|
||||
ChangeLog | 7 +++++++
|
||||
elf/dl-load.c | 34 ++++++++++++++++------------------
|
||||
2 files changed, 23 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c
|
||||
index 18a83d2..6e16a9a 100644
|
||||
--- a/elf/dl-load.c
|
||||
+++ b/elf/dl-load.c
|
||||
@@ -249,8 +249,7 @@ is_trusted_path_normalize (const char *path, size_t len)
|
||||
|
||||
|
||||
static size_t
|
||||
-is_dst (const char *start, const char *name, const char *str,
|
||||
- int is_path, int secure)
|
||||
+is_dst (const char *start, const char *name, const char *str, int is_path)
|
||||
{
|
||||
size_t len;
|
||||
bool is_curly = false;
|
||||
@@ -279,12 +278,6 @@ is_dst (const char *start, const char *name, const char *str,
|
||||
&& (!is_path || name[len] != ':'))
|
||||
return 0;
|
||||
|
||||
- if (__glibc_unlikely (secure)
|
||||
- && ((name[len] != '\0' && name[len] != '/'
|
||||
- && (!is_path || name[len] != ':'))
|
||||
- || (name != start + 1 && (!is_path || name[-2] != ':'))))
|
||||
- return 0;
|
||||
-
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -299,13 +292,10 @@ _dl_dst_count (const char *name, int is_path)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
- /* $ORIGIN is not expanded for SUID/GUID programs (except if it
|
||||
- is $ORIGIN alone) and it must always appear first in path. */
|
||||
++name;
|
||||
- if ((len = is_dst (start, name, "ORIGIN", is_path,
|
||||
- __libc_enable_secure)) != 0
|
||||
- || (len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0
|
||||
- || (len = is_dst (start, name, "LIB", is_path, 0)) != 0)
|
||||
+ if ((len = is_dst (start, name, "ORIGIN", is_path)) != 0
|
||||
+ || (len = is_dst (start, name, "PLATFORM", is_path)) != 0
|
||||
+ || (len = is_dst (start, name, "LIB", is_path)) != 0)
|
||||
++cnt;
|
||||
|
||||
name = strchr (name + len, '$');
|
||||
@@ -338,10 +328,18 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
|
||||
size_t len;
|
||||
|
||||
++name;
|
||||
- if ((len = is_dst (start, name, "ORIGIN", is_path,
|
||||
- __libc_enable_secure)) != 0)
|
||||
+ if ((len = is_dst (start, name, "ORIGIN", is_path)) != 0)
|
||||
{
|
||||
- repl = l->l_origin;
|
||||
+ /* For SUID/GUID programs $ORIGIN must always appear
|
||||
+ first in a path element. */
|
||||
+ if (__glibc_unlikely (__libc_enable_secure)
|
||||
+ && ((name[len] != '\0' && name[len] != '/'
|
||||
+ && (!is_path || name[len] != ':'))
|
||||
+ || (name != start + 1 && (!is_path || name[-2] != ':'))))
|
||||
+ repl = (const char *) -1;
|
||||
+ else
|
||||
+ repl = l->l_origin;
|
||||
+
|
||||
check_for_trusted = (__libc_enable_secure
|
||||
&& l->l_type == lt_executable);
|
||||
}
|
||||
@@ -351,9 +348,9 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
|
||||
check_for_trusted = (__libc_enable_secure
|
||||
&& l->l_type == lt_executable);
|
||||
}
|
||||
- else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0)
|
||||
+ else if ((len = is_dst (start, name, "PLATFORM", is_path)) != 0)
|
||||
repl = GLRO(dl_platform);
|
||||
- else if ((len = is_dst (start, name, "LIB", is_path, 0)) != 0)
|
||||
+ else if ((len = is_dst (start, name, "LIB", is_path)) != 0)
|
||||
repl = DL_DST_LIB;
|
||||
|
||||
if (repl != NULL && repl != (const char *) -1)
|
||||
@@ -373,6 +370,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
|
||||
element, but keep an empty element at the end. */
|
||||
if (wp == result && is_path && *name == ':' && name[1] != '\0')
|
||||
++name;
|
||||
+ check_for_trusted = false;
|
||||
}
|
||||
else
|
||||
/* No DST we recognize. */
|
18
glibc-fedora-i386-tls-direct-seg-refs.patch
Normal file
18
glibc-fedora-i386-tls-direct-seg-refs.patch
Normal file
@ -0,0 +1,18 @@
|
||||
diff -Nrup a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile
|
||||
--- a/sysdeps/i386/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/sysdeps/i386/Makefile 2012-06-07 12:15:21.826318641 -0600
|
||||
@@ -62,6 +64,14 @@ endif
|
||||
|
||||
ifneq (,$(filter -mno-tls-direct-seg-refs,$(CFLAGS)))
|
||||
defines += -DNO_TLS_DIRECT_SEG_REFS
|
||||
+else
|
||||
+# .a libraries are not performance critical and so we
|
||||
+# build them without direct TLS segment references
|
||||
+# always.
|
||||
+CPPFLAGS-.o += -DNO_TLS_DIRECT_SEG_REFS
|
||||
+CFLAGS-.o += -mno-tls-direct-seg-refs
|
||||
+CPPFLAGS-.oS += -DNO_TLS_DIRECT_SEG_REFS
|
||||
+CFLAGS-.oS += -mno-tls-direct-seg-refs
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),elf)
|
30
glibc-fedora-include-bits-ldbl.patch
Normal file
30
glibc-fedora-include-bits-ldbl.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 5eb4509a6651d19c7a28c4506d6aa582c9ee095a Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Wed, 1 Feb 2006 09:30:43 +0000
|
||||
Subject: [PATCH] 128-bit long double fixes
|
||||
|
||||
* include/bits/stdlib-ldbl.h: New file.
|
||||
* include/bits/wchar-ldbl.h: New file.
|
||||
|
||||
---
|
||||
ChangeLog | 5 +++++
|
||||
include/bits/stdlib-ldbl.h | 1 +
|
||||
include/bits/wchar-ldbl.h | 1 +
|
||||
3 files changed, 7 insertions(+), 0 deletions(-)
|
||||
create mode 100644 include/bits/stdlib-ldbl.h
|
||||
create mode 100644 include/bits/wchar-ldbl.h
|
||||
|
||||
diff --git a/include/bits/stdlib-ldbl.h b/include/bits/stdlib-ldbl.h
|
||||
new file mode 100644
|
||||
index 0000000..6250949
|
||||
--- /dev/null
|
||||
+++ b/include/bits/stdlib-ldbl.h
|
||||
@@ -0,0 +1 @@
|
||||
+#include <stdlib/bits/stdlib-ldbl.h>
|
||||
diff --git a/include/bits/wchar-ldbl.h b/include/bits/wchar-ldbl.h
|
||||
new file mode 100644
|
||||
index 0000000..29baa2f
|
||||
--- /dev/null
|
||||
+++ b/include/bits/wchar-ldbl.h
|
||||
@@ -0,0 +1 @@
|
||||
+#include <wcsmbs/bits/wchar-ldbl.h>
|
42
glibc-fedora-ldd.patch
Normal file
42
glibc-fedora-ldd.patch
Normal file
@ -0,0 +1,42 @@
|
||||
From 83e5edd390eabe8f8e8e0d051f929b77a30c0767 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schwab <schwab@redhat.com>
|
||||
Date: Fri, 18 Mar 2011 16:22:52 +0100
|
||||
Subject: [PATCH] ldd: never run file directly
|
||||
|
||||
* elf/ldd.bash.in: Never run file directly.
|
||||
|
||||
---
|
||||
ChangeLog | 4 ++++
|
||||
elf/ldd.bash.in | 14 +-------------
|
||||
2 files changed, 5 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/elf/ldd.bash.in
|
||||
+++ b/elf/ldd.bash.in
|
||||
@@ -166,18 +166,6 @@ warning: you do not have execution permission for" "\`$file'" >&2
|
||||
fi
|
||||
done
|
||||
case $ret in
|
||||
- 0)
|
||||
- # If the program exits with exit code 5, it means the process has been
|
||||
- # invoked with __libc_enable_secure. Fall back to running it through
|
||||
- # the dynamic linker.
|
||||
- try_trace "$file"
|
||||
- rc=$?
|
||||
- if [ $rc = 5 ]; then
|
||||
- try_trace "$RTLD" "$file"
|
||||
- rc=$?
|
||||
- fi
|
||||
- [ $rc = 0 ] || result=1
|
||||
- ;;
|
||||
1)
|
||||
# This can be a non-ELF binary or no binary at all.
|
||||
nonelf "$file" || {
|
||||
@@ -185,7 +173,7 @@ warning: you do not have execution permission for" "\`$file'" >&2
|
||||
result=1
|
||||
}
|
||||
;;
|
||||
- 2)
|
||||
+ 0|2)
|
||||
try_trace "$RTLD" "$file" || result=1
|
||||
;;
|
||||
*)
|
@ -1,19 +1,7 @@
|
||||
Short description: Fedora-specific workaround for kernel pty bug.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-submitted
|
||||
|
||||
This is a Fedora-specific workaround for a kernel bug where calling
|
||||
ioctl on a pty will silently ignore the invalid c_cflag. The
|
||||
workaround is to use TCGETS to verify the setting matches. This is
|
||||
not upstream and needs to either be removed or submitted upstream
|
||||
after analysis.
|
||||
|
||||
Index: b/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
===================================================================
|
||||
--- a/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
@@ -45,6 +45,7 @@ __tcsetattr (int fd, int optional_action
|
||||
diff -Nrup a/sysdeps/unix/sysv/linux/tcsetattr.c b/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
--- a/sysdeps/unix/sysv/linux/tcsetattr.c 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c 2012-06-07 12:15:21.831318623 -0600
|
||||
@@ -48,6 +48,7 @@ tcsetattr (fd, optional_actions, termios
|
||||
{
|
||||
struct __kernel_termios k_termios;
|
||||
unsigned long int cmd;
|
||||
@ -21,7 +9,7 @@ Index: b/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
|
||||
switch (optional_actions)
|
||||
{
|
||||
@@ -75,7 +76,36 @@ __tcsetattr (int fd, int optional_action
|
||||
@@ -79,6 +80,35 @@ tcsetattr (fd, optional_actions, termios
|
||||
memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0],
|
||||
__KERNEL_NCCS * sizeof (cc_t));
|
||||
|
||||
@ -57,5 +45,4 @@ Index: b/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
+
|
||||
+ return retval;
|
||||
}
|
||||
weak_alias (__tcsetattr, tcsetattr)
|
||||
libc_hidden_def (tcsetattr)
|
||||
|
@ -1,14 +1,3 @@
|
||||
Short description: Add 4 ISO-8859-15 locales to SUPPORTED for Euro symbol.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #61908
|
||||
Upstream status: not-needed
|
||||
|
||||
Very early RHL 7.3 requirement to add these locales so users can
|
||||
get access to Euro symbol. We should review this bug and decide if
|
||||
the UTF-8 locales are now serving the same purpose and drop the
|
||||
additional locales.
|
||||
|
||||
* Tue Mar 26 2002 Jakub Jelinek <jakub@redhat.com> 2.2.5-28
|
||||
- add a couple of .ISO-8859-15 locales (#61908)
|
||||
|
||||
|
@ -1,21 +1,11 @@
|
||||
Short description: Fedora-specific glibc install locale changes.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
The Fedora glibc build and install does not need the normal install
|
||||
behaviour which updates the locale archive. The Fedora install phase
|
||||
in the spec file of the rpm will handle this manually.
|
||||
|
||||
diff --git a/localedata/Makefile b/localedata/Makefile
|
||||
index 0eea396ad86da956..54caabda33728207 100644
|
||||
--- a/localedata/Makefile
|
||||
+++ b/localedata/Makefile
|
||||
@@ -413,6 +413,7 @@ define build-one-locale
|
||||
diff -Nrup a/localedata/Makefile b/localedata/Makefile
|
||||
--- a/localedata/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/localedata/Makefile 2012-06-07 12:15:21.776318827 -0600
|
||||
@@ -211,6 +211,7 @@ $(INSTALL-SUPPORTED-LOCALES): install-lo
|
||||
echo -n '...'; \
|
||||
input=`echo $$locale | sed 's/\([^.]*\)[^@]*\(.*\)/\1\2/'`; \
|
||||
$(LOCALEDEF) $$flags --alias-file=../intl/locale.alias \
|
||||
$(LOCALEDEF) --alias-file=../intl/locale.alias \
|
||||
+ --no-archive \
|
||||
-i locales/$$input -f charmaps/$$charset \
|
||||
-i locales/$$input -c -f charmaps/$$charset \
|
||||
$(addprefix --prefix=,$(install_root)) $$locale \
|
||||
&& echo ' done';
|
||||
&& echo ' done'; \
|
||||
|
51
glibc-fedora-locarchive.patch
Normal file
51
glibc-fedora-locarchive.patch
Normal file
@ -0,0 +1,51 @@
|
||||
This is a part of commit glibc-2.3.3-1492-ga891c7b,
|
||||
needed for fedora/build-locale-archive.c only.
|
||||
|
||||
diff -Nrup a/ChangeLog.17 b/ChangeLog.17
|
||||
--- a/ChangeLog.17 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/ChangeLog.17 2012-06-07 12:15:21.564319619 -0600
|
||||
@@ -11818,6 +11829,10 @@ d2009-10-30 Ulrich Drepper <drepper@re
|
||||
[BZ #4368]
|
||||
* stdlib/stdlib.h: Remove obsolete part of comment for realpath.
|
||||
|
||||
+2007-04-16 Jakub Jelinek <jakub@redhat.com>
|
||||
+
|
||||
+ * locale/programs/locarchive.c (add_alias, insert_name): Remove static.
|
||||
+
|
||||
2007-04-16 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
[BZ #4364]
|
||||
diff -Nrup a/locale/programs/locarchive.c b/locale/programs/locarchive.c
|
||||
--- a/locale/programs/locarchive.c 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/locale/programs/locarchive.c 2012-06-07 12:15:21.585319540 -0600
|
||||
@@ -252,9 +252,9 @@ oldlocrecentcmp (const void *a, const vo
|
||||
/* forward decls for below */
|
||||
static uint32_t add_locale (struct locarhandle *ah, const char *name,
|
||||
locale_data_t data, bool replace);
|
||||
-static void add_alias (struct locarhandle *ah, const char *alias,
|
||||
- bool replace, const char *oldname,
|
||||
- uint32_t *locrec_offset_p);
|
||||
+void add_alias (struct locarhandle *ah, const char *alias,
|
||||
+ bool replace, const char *oldname,
|
||||
+ uint32_t *locrec_offset_p);
|
||||
|
||||
|
||||
static bool
|
||||
@@ -635,7 +635,7 @@ close_archive (struct locarhandle *ah)
|
||||
#include "../../intl/explodename.c"
|
||||
#include "../../intl/l10nflist.c"
|
||||
|
||||
-static struct namehashent *
|
||||
+struct namehashent *
|
||||
insert_name (struct locarhandle *ah,
|
||||
const char *name, size_t name_len, bool replace)
|
||||
{
|
||||
@@ -693,7 +693,7 @@ insert_name (struct locarhandle *ah,
|
||||
return &namehashtab[idx];
|
||||
}
|
||||
|
||||
-static void
|
||||
+void
|
||||
add_alias (struct locarhandle *ah, const char *alias, bool replace,
|
||||
const char *oldname, uint32_t *locrec_offset_p)
|
||||
{
|
@ -1,14 +1,3 @@
|
||||
Short description: Place glibc info into "Libraries" category.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
The category names for libraries is completely random including
|
||||
"Libraries", "GNU Libraries", "GNU libraries", and "Software libraries."
|
||||
In the GNU info manual the "Software libraries" category is given as an
|
||||
example, but really we need to standardize on a category for upstream.
|
||||
I suggest we drop this change after some upstream discussion.
|
||||
|
||||
From 4820b9175535e13df79ce816106016040014916e Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Fri, 3 Nov 2006 16:31:21 +0000
|
||||
|
@ -1,13 +1,3 @@
|
||||
Short description: Fedora-specific enabling batch read in NSS.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #188246
|
||||
Upstream status: not-submitted
|
||||
|
||||
Enable batch read in NSS. It's not clear if this is always a win or
|
||||
just a win for NIS+, this needs to be analyzed and sent upstream or
|
||||
removed.
|
||||
|
||||
From baba5d9461d4e8a581ac26fe4412ad783ffc73e7 Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Mon, 1 May 2006 08:02:53 +0000
|
||||
|
25
glibc-fedora-nptl-linklibc.patch
Normal file
25
glibc-fedora-nptl-linklibc.patch
Normal file
@ -0,0 +1,25 @@
|
||||
diff -Nrup a/nptl/Makefile b/nptl/Makefile
|
||||
--- a/nptl/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/nptl/Makefile 2012-06-07 12:15:21.816318678 -0600
|
||||
@@ -529,15 +529,19 @@ $(addprefix $(objpfx), \
|
||||
$(tests) $(xtests) $(test-srcs))): $(objpfx)libpthread.so \
|
||||
$(objpfx)libpthread_nonshared.a
|
||||
$(objpfx)tst-unload: $(libdl)
|
||||
-# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
|
||||
+# $(objpfx)linklibc.so is used instead of $(common-objpfx)libc.so,
|
||||
# since otherwise libpthread.so comes before libc.so when linking.
|
||||
$(addprefix $(objpfx), $(tests-reverse)): \
|
||||
- $(objpfx)../libc.so $(objpfx)libpthread.so \
|
||||
+ $(objpfx)linklibc.so $(objpfx)libpthread.so \
|
||||
$(objpfx)libpthread_nonshared.a
|
||||
$(objpfx)../libc.so: $(common-objpfx)libc.so ;
|
||||
$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a
|
||||
|
||||
$(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so
|
||||
+
|
||||
+$(objpfx)linklibc.so: $(common-objpfx)libc.so
|
||||
+ ln -s ../libc.so $@
|
||||
+generated += libclink.so
|
||||
else
|
||||
$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
|
||||
endif
|
@ -1,11 +1,3 @@
|
||||
Short description: NSCD must use nscd user.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
Fedora-specific configuration adjustment to introduce the nscd user.
|
||||
(Upstream does not assume this user exists.)
|
||||
|
||||
diff -Nrup a/nscd/nscd.conf b/nscd/nscd.conf
|
||||
--- a/nscd/nscd.conf 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/nscd/nscd.conf 2012-06-07 12:15:21.818318670 -0600
|
||||
|
@ -1,45 +0,0 @@
|
||||
The Fedora /etc/nsswitch.conf is based largely on the upstream
|
||||
version with minor downstream distribution modifications for
|
||||
use with SSSD and systemd.
|
||||
|
||||
diff --git a/nss/nsswitch.conf b/nss/nsswitch.conf
|
||||
index f55358811495c9f1..14c3cde8080a848c 100644
|
||||
--- a/nss/nsswitch.conf
|
||||
+++ b/nss/nsswitch.conf
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# /etc/nsswitch.conf
|
||||
#
|
||||
-# An example Name Service Switch config file. This file should be
|
||||
+# Name Service Switch config file. This file should be
|
||||
# sorted with the most-used services at the beginning.
|
||||
#
|
||||
# Valid databases are: aliases, ethers, group, gshadow, hosts,
|
||||
@@ -52,18 +52,20 @@
|
||||
# shadow: db files
|
||||
# group: db files
|
||||
|
||||
-# In alphabetical order. Re-order as required to optimize peformance.
|
||||
+# In order of likelihood of use to accelerate lookup.
|
||||
+passwd: sss files
|
||||
+shadow: files sss
|
||||
+group: sss files
|
||||
+hosts: files dns myhostname
|
||||
+services: files sss
|
||||
+netgroup: sss
|
||||
+automount: files sss
|
||||
+
|
||||
aliases: files
|
||||
ethers: files
|
||||
-group: files
|
||||
gshadow: files
|
||||
-hosts: files dns
|
||||
initgroups: files
|
||||
-netgroup: files
|
||||
networks: files dns
|
||||
-passwd: files
|
||||
protocols: files
|
||||
publickey: files
|
||||
rpc: files
|
||||
-shadow: files
|
||||
-services: files
|
20
glibc-fedora-ppc-unwind.patch
Normal file
20
glibc-fedora-ppc-unwind.patch
Normal file
@ -0,0 +1,20 @@
|
||||
glibc-2.3.3-1478-g37582bc
|
||||
|
||||
* Thu Nov 30 2006 Jakub Jelinek <jakub@redhat.com> 2.5.90-9
|
||||
- on ppc64 build __libc_start_main without unwind info,
|
||||
as it breaks MD_FROB_UPDATE_CONTEXT (#217729, #217775; in the
|
||||
future that could be fixable just by providing .cfi_undefined r2
|
||||
in __libc_start_main instead)
|
||||
|
||||
diff -Nrup a/sysdeps/powerpc/powerpc64/Makefile b/sysdeps/powerpc/powerpc64/Makefile
|
||||
--- a/sysdeps/powerpc/powerpc64/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/sysdeps/powerpc/powerpc64/Makefile 2012-06-07 12:15:21.828318633 -0600
|
||||
@@ -35,6 +35,8 @@ CFLAGS-rtld-memmove.os = $(no-special-re
|
||||
CFLAGS-rtld-memchr.os = $(no-special-regs)
|
||||
CFLAGS-rtld-strnlen.os = $(no-special-regs)
|
||||
|
||||
+CFLAGS-libc-start.c += -fno-asynchronous-unwind-tables
|
||||
+
|
||||
ifeq ($(subdir),elf)
|
||||
# help gcc inline asm code from dl-machine.h
|
||||
+cflags += -finline-limit=2000
|
28
glibc-fedora-streams-rh436349.patch
Normal file
28
glibc-fedora-streams-rh436349.patch
Normal file
@ -0,0 +1,28 @@
|
||||
This is part of commit glibc-2.3.3-1564-gd0b6ac6
|
||||
|
||||
* Fri Mar 14 2008 Jakub Jelinek <jakub@redhat.com> 2.7.90-11
|
||||
- remove <stropts.h>, define _XOPEN_STREAMS -1 (#436349)
|
||||
|
||||
diff -Nrup a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
|
||||
--- a/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-07 12:15:21.817318674 -0600
|
||||
@@ -188,4 +188,7 @@
|
||||
/* Typed memory objects are not available. */
|
||||
#define _POSIX_TYPED_MEMORY_OBJECTS -1
|
||||
|
||||
+/* Streams are not available. */
|
||||
+#define _XOPEN_STREAMS -1
|
||||
+
|
||||
#endif /* bits/posix_opt.h */
|
||||
diff -Nrup a/streams/Makefile b/streams/Makefile
|
||||
--- a/streams/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/streams/Makefile 2012-06-07 12:15:21.824318649 -0600
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
-headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
|
||||
+#headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
|
||||
routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach
|
||||
|
||||
include ../Rules
|
50
glibc-fedora-uname-getrlimit.patch
Normal file
50
glibc-fedora-uname-getrlimit.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From cde99cd2b7b16a6113acb054e89d490047932a9f Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schwab <schwab@redhat.com>
|
||||
Date: Thu, 8 Apr 2010 11:18:26 +0200
|
||||
Subject: [PATCH] Don't call uname or getrlimit in libpthread init function
|
||||
|
||||
* sysdeps/unix/sysv/linux/i386/Versions: Export __uname under
|
||||
GLIBC_PRIVATE.
|
||||
* nptl/Versions: Export __getrlimit under GLIBC_PRIVATE.
|
||||
* sysdeps/unix/sysv/linux/i386/smp.h: Call __uname instead of uname.
|
||||
* nptl/nptl-init.c: Call __getrlimit instead of getrlimit.
|
||||
|
||||
---
|
||||
ChangeLog | 8 ++++++++
|
||||
nptl/Versions | 1 +
|
||||
nptl/nptl-init.c | 2 +-
|
||||
sysdeps/unix/sysv/linux/i386/Versions | 6 ++++++
|
||||
sysdeps/unix/sysv/linux/i386/smp.h | 2 +-
|
||||
5 files changed, 17 insertions(+), 2 deletions(-)
|
||||
create mode 100644 sysdeps/unix/sysv/linux/i386/Versions
|
||||
|
||||
--- a/nptl/Version
|
||||
+++ b/nptl/Versions
|
||||
@@ -30,6 +30,7 @@ libc {
|
||||
__libc_pthread_init;
|
||||
__libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
|
||||
__libc_allocate_rtsig_private;
|
||||
+ __getrlimit;
|
||||
}
|
||||
}
|
||||
|
||||
--- a/sysdeps/unix/sysv/linux/i386/Versions
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/Versions
|
||||
@@ -53,5 +53,6 @@
|
||||
}
|
||||
GLIBC_PRIVATE {
|
||||
__modify_ldt;
|
||||
+ __uname;
|
||||
}
|
||||
}
|
||||
--- a/sysdeps/unix/sysv/linux/i386/smp.h
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/smp.h
|
||||
@@ -36,7 +36,7 @@ is_smp_system (void)
|
||||
char *cp;
|
||||
|
||||
/* Try reading the number using `sysctl' first. */
|
||||
- if (uname (&u.uts) == 0)
|
||||
+ if (__uname (&u.uts) == 0)
|
||||
cp = u.uts.version;
|
||||
else
|
||||
{
|
2706
glibc-fedora-use-test-skeleton.patch
Normal file
2706
glibc-fedora-use-test-skeleton.patch
Normal file
File diff suppressed because it is too large
Load Diff
32
glibc-gethnamaddr-gcc5.patch
Normal file
32
glibc-gethnamaddr-gcc5.patch
Normal file
@ -0,0 +1,32 @@
|
||||
Index: glibc-2.22-193-g315267a/resolv/gethnamaddr.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/resolv/gethnamaddr.c
|
||||
+++ glibc-2.22-193-g315267a/resolv/gethnamaddr.c
|
||||
@@ -71,6 +71,7 @@ static char sccsid[] = "@(#)gethostnamad
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
#define RESOLVSORT
|
||||
|
||||
@@ -986,10 +987,19 @@ addrsort(ap, num)
|
||||
|
||||
p = ap;
|
||||
for (i = 0; i < num; i++, p++) {
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since i is limited to
|
||||
+ _res.nsort which is limited to MAXRESOLVSORT. This
|
||||
+ is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (j = 0 ; (unsigned)j < _res.nsort; j++)
|
||||
if (_res.sort_list[j].addr.s_addr ==
|
||||
(((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
|
||||
break;
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
aval[i] = j;
|
||||
if (needsort == 0 && i > 0 && j < aval[i-1])
|
||||
needsort = i;
|
72
glibc-ld-ctype-gcc5.patch
Normal file
72
glibc-ld-ctype-gcc5.patch
Normal file
@ -0,0 +1,72 @@
|
||||
Index: glibc-2.22-193-g315267a/locale/programs/ld-ctype.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/locale/programs/ld-ctype.c
|
||||
+++ glibc-2.22-193-g315267a/locale/programs/ld-ctype.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <wctype.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/uio.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
#include "localedef.h"
|
||||
#include "charmap.h"
|
||||
@@ -2534,9 +2535,19 @@ with character code range values one mus
|
||||
{
|
||||
size_t cnt;
|
||||
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not possible since ctype_map_new prevents
|
||||
+ map_collection_nr from being greater than MAX_NR_CHARMP which
|
||||
+ is the size of mapnames. This is likely PR/59124 which is still
|
||||
+ not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (cnt = 2; cnt < ctype->map_collection_nr; ++cnt)
|
||||
if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
|
||||
break;
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
if (cnt < ctype->map_collection_nr)
|
||||
free (now->val.str.startmb);
|
||||
@@ -2807,9 +2818,19 @@ previous definition was here")));
|
||||
|
||||
/* This could mean one of several things. First test whether
|
||||
it's a character class name. */
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not possible since ctype_class_new prevents
|
||||
+ nr_charclass from being greater than MAX_NR_CHARCLASS which
|
||||
+ is the size of classnames. This is likely PR/59124 which is still
|
||||
+ not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
|
||||
if (strcmp (now->val.str.startmb, ctype->classnames[cnt]) == 0)
|
||||
break;
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
if (cnt < ctype->nr_charclass)
|
||||
{
|
||||
class_bit = _ISwbit (cnt);
|
||||
@@ -2817,9 +2838,19 @@ previous definition was here")));
|
||||
free (now->val.str.startmb);
|
||||
goto read_charclass;
|
||||
}
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not possible since ctype_map_new prevents
|
||||
+ map_collection_nr from being greater than MAX_NR_CHARMP which
|
||||
+ is the size of mapnames. This is likely PR/59124 which is still
|
||||
+ not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (cnt = 0; cnt < ctype->map_collection_nr; ++cnt)
|
||||
if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
|
||||
break;
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
if (cnt < ctype->map_collection_nr)
|
||||
{
|
||||
mapidx = cnt;
|
@ -1,10 +1,3 @@
|
||||
Short description: Provide options to nscd startup.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
Fedora-specific nscd startup configuration file.
|
||||
|
||||
diff --git a/nscd/nscd.service b/nscd/nscd.service
|
||||
index b7428a3..19ba185 100644
|
||||
--- a/nscd/nscd.service
|
||||
|
858
glibc-nsswitch-Add-group-merging-support.patch
Normal file
858
glibc-nsswitch-Add-group-merging-support.patch
Normal file
@ -0,0 +1,858 @@
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: nsswitch: Add group merging support
|
||||
From: Stephen Gallagher <sgallagh@redhat.com>
|
||||
X-Patchwork-Id: 10289
|
||||
Message-Id: <1452213991-6499-1-git-send-email-sgallagh@redhat.com>
|
||||
To: libc-alpha@sourceware.org
|
||||
Date: Thu, 7 Jan 2016 19:46:31 -0500
|
||||
|
||||
https://sourceware.org/glibc/wiki/Proposals/GroupMerging
|
||||
|
||||
== Justification ==
|
||||
It is common today for users to rely on centrally-managed user stores for
|
||||
handling their user accounts. However, much software existing today does
|
||||
not have an innate understanding of such accounts. Instead, they commonly
|
||||
rely on membership in known groups for managing access-control (for
|
||||
example the "wheel" group on Fedora and RHEL systems or the "adm" group
|
||||
on Debian-derived systems). In the present incarnation of nsswitch, the
|
||||
only way to have such groups managed by a remote user store such as
|
||||
FreeIPA or Active Directory would be to manually remove the groups from
|
||||
/etc/group on the clients so that nsswitch would then move past nss_files
|
||||
and into the SSSD, nss-ldap or other remote user database.
|
||||
|
||||
== Solution ==
|
||||
With this patch, a new action is introduced for nsswitch:
|
||||
NSS_ACTION_MERGE. To take advantage of it, one will add [SUCCESS=merge]
|
||||
between two database entries in the nsswitch.conf file. When a group is
|
||||
located in the first of the two group entries, processing will continue
|
||||
on to the next one. If the group is also found in the next entry (and the
|
||||
group name and GID are an exact match), the member list of the second
|
||||
entry will be added to the group object to be returned.
|
||||
|
||||
== Implementation ==
|
||||
After each DL_LOOKUP_FN() returns, the next action is checked. If the
|
||||
function returned NSS_STATUS_SUCCESS and the next action is
|
||||
NSS_ACTION_MERGE, a copy of the result buffer is saved for the next pass
|
||||
through the loop. If on this next pass through the loop the database
|
||||
returns another instance of a group matching both the group name and GID,
|
||||
the member list is added to the previous list and it is returned as a
|
||||
single object. If the following database does not contain the same group,
|
||||
then the original is copied back into the destination buffer.
|
||||
|
||||
This patch implements merge functionality only for the group database.
|
||||
For other databases, there is a default implementation that will return
|
||||
the EINVAL errno if a merge is requested. The merge functionality can be
|
||||
implemented for other databases at a later time if such is needed. Each
|
||||
database must provide a unique implementation of the deep-copy and merge
|
||||
functions.
|
||||
|
||||
If [SUCCESS=merge] is present in nsswitch.conf for a glibc version that
|
||||
does not support it, glibc will process results up until that operation,
|
||||
at which time it will return results if it has found them or else will
|
||||
simply return an error. In practical terms, this ends up behaving like
|
||||
the remainder of the nsswitch.conf line does not exist.
|
||||
|
||||
== Iterators ==
|
||||
This feature does not modify the iterator functionality from its current
|
||||
behavior. If getgrnam() or getgrgid() is called, glibc will iterate
|
||||
through all entries in the `group` line in nsswitch.conf and display the
|
||||
list of members without attempting to merge them. This is consistent with
|
||||
the behavior of nss_files where if two separate lines are specified for
|
||||
the same group in /etc/groups, getgrnam()/getgrgid() will display both.
|
||||
Clients are already expected to handle this gracefully.
|
||||
|
||||
== No Premature Optimizations ==
|
||||
The following is a list of places that might be eligible for
|
||||
optimization, but were not overengineered for this initial contribution:
|
||||
* Any situation where a merge may occur will result in one malloc() of
|
||||
the same size as the input buffer.
|
||||
* Any situation where a merge does occur will result in a second
|
||||
malloc() to hold the list of pointers to member name strings.
|
||||
* The list of members is simply concatenated together and is not tested
|
||||
for uniqueness (which is identical to the behavior for nss_files,
|
||||
which will simply return identical values if they both exist on the
|
||||
line in the file. This could potentially be optimized to reduce space
|
||||
usage in the buffer, but it is both complex and computationally
|
||||
expensive to do so.
|
||||
|
||||
== Testing ==
|
||||
I performed testing by running the getent utility against my newly-built
|
||||
glibc and configuring /etc/nsswitch.conf with the following entry:
|
||||
group: group: files [SUCCESS=merge] sss
|
||||
|
||||
In /etc/group I included the line:
|
||||
wheel:x:10:sgallagh
|
||||
|
||||
I then configured my local SSSD using the id_provider=local to respond
|
||||
with:
|
||||
wheel:*:10:localuser,localuser2
|
||||
|
||||
I then ran `getent group wheel` against the newly-built glibc in
|
||||
multiple situations and received the expected output as described
|
||||
above:
|
||||
* When SSSD was running.
|
||||
* When SSSD was configured in nsswitch.conf but the daemon was not
|
||||
running.
|
||||
* When SSSD was configured in nsswitch.conf but nss_sss.so.2 was not
|
||||
installed on the system.
|
||||
* When the order of 'sss' and 'files' was reversed.
|
||||
* All of the above with the [SUCCESS=merge] removed (to ensure no
|
||||
regressions).
|
||||
* All of the above with `getent group 10`.
|
||||
* All of the above with `getent group` with and without
|
||||
`enumerate=true` set in SSSD.
|
||||
* All of the above with and without nscd enabled on the system.
|
||||
|
||||
== NEWS ==
|
||||
|
||||
* A new NSS action is added to facilitate large distribution system
|
||||
administration. The action, MERGE, allows remote user stores like
|
||||
LDAP to be merged into local user stores like /etc/groups in order
|
||||
to provide easy to use, updated, and managed sets of merged
|
||||
credentials. The new action can be used by configuring it in
|
||||
/etc/nsswitch.conf:
|
||||
group: files [SUCCESS=merge] nis
|
||||
Implemented by Stephen Gallagher (Red Hat).
|
||||
|
||||
== ChangeLog ==
|
||||
|
||||
2015-12-16 Stephen Gallagher <sgallagh@redhat.com>
|
||||
|
||||
[BZ #19072]
|
||||
* grp/Makefile (headers): Add grp-merge.h
|
||||
(routines): Add grp-merge.
|
||||
* grp/getgrgid_r.c: Include grp-merge.h.
|
||||
(DEEPCOPY_FN): Define.
|
||||
(MERGE_FN): Define.
|
||||
* grp/getgrname_r.c: Include grp-merge.h.
|
||||
(DEEPCOPY_FN): Define.
|
||||
(MERGE_FN): Define.
|
||||
* grp/grp-merge.c: New file.
|
||||
* grp/grp-merge.h: New file.
|
||||
* manual/nss.texi (Actions in the NSS configuration): Describe
|
||||
return, continue, and merge.
|
||||
* nscd/Makefile: Add vpath to find grp-merge.c
|
||||
(nscd-modules): Add grp-merge.
|
||||
* nscd/getgrgid_r.c: Include grp/grp-merge.h.
|
||||
(DEEPCOPY_FN): Define.
|
||||
(MERGE_FN): Define.
|
||||
* nscd/getgrnam_r.c: Include grp/grp-merge.h.
|
||||
(DEEPCOPY_FN): Define.
|
||||
(MERGE_FN): Define.
|
||||
* nss/getXXbyYY_r.c [!DEEPCOPY_FN]: Define __copy_einval.
|
||||
[!MERGE_FN]: Define __merge_einval.
|
||||
(CHECK_MERGE): Define.
|
||||
(REENTRANT_NAME): Process merge if do_merge is true.
|
||||
* nss/getnssent_r.c (__nss_setent): Process NSS_ACTION_MERGE.
|
||||
(__nss_getent_r): Likewise.
|
||||
* nss/nsswitch.c (nss_parse_service_list): Likewise.
|
||||
* nss/nsswitch.h (lookup_actions): Define NSS_ACTION_MERGE.
|
||||
|
||||
Resolves BZ #19072
|
||||
|
||||
---
|
||||
grp/Makefile | 5 +-
|
||||
grp/getgrgid_r.c | 3 +
|
||||
grp/getgrnam_r.c | 4 ++
|
||||
grp/grp-merge.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
grp/grp-merge.h | 35 +++++++++++
|
||||
manual/nss.texi | 46 +++++++++++++-
|
||||
nscd/Makefile | 5 +-
|
||||
nscd/getgrgid_r.c | 4 ++
|
||||
nscd/getgrnam_r.c | 4 ++
|
||||
nss/getXXbyYY_r.c | 105 +++++++++++++++++++++++++++++++-
|
||||
nss/getnssent_r.c | 34 ++++++++++-
|
||||
nss/nsswitch.c | 3 +
|
||||
nss/nsswitch.h | 3 +-
|
||||
13 files changed, 419 insertions(+), 10 deletions(-)
|
||||
create mode 100644 grp/grp-merge.c
|
||||
create mode 100644 grp/grp-merge.h
|
||||
|
||||
diff --git a/grp/Makefile b/grp/Makefile
|
||||
index ed8cc2b0564f0e3842cd78f24a4e0788d659bbc4..52af992365268aae8cf8a80cd7216160b1431e84 100644
|
||||
--- a/grp/Makefile
|
||||
+++ b/grp/Makefile
|
||||
@@ -20,15 +20,16 @@
|
||||
#
|
||||
subdir := grp
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
-headers := grp.h
|
||||
+headers := grp.h grp-merge.h
|
||||
|
||||
routines := fgetgrent initgroups setgroups \
|
||||
getgrent getgrgid getgrnam putgrent \
|
||||
- getgrent_r getgrgid_r getgrnam_r fgetgrent_r
|
||||
+ getgrent_r getgrgid_r getgrnam_r fgetgrent_r \
|
||||
+ grp-merge
|
||||
|
||||
tests := testgrp tst-putgrent
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
test-srcs := tst_fgetgrent
|
||||
diff --git a/grp/getgrgid_r.c b/grp/getgrgid_r.c
|
||||
index 05d4d772d3ef0bfae8f9375387c41310885ce41a..447fa633807deec8f26d654ebeb6386a150d3a37 100644
|
||||
--- a/grp/getgrgid_r.c
|
||||
+++ b/grp/getgrgid_r.c
|
||||
@@ -16,14 +16,17 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <grp.h>
|
||||
|
||||
+#include "grp-merge.h"
|
||||
|
||||
#define LOOKUP_TYPE struct group
|
||||
#define FUNCTION_NAME getgrgid
|
||||
#define DATABASE_NAME group
|
||||
#define ADD_PARAMS gid_t gid
|
||||
#define ADD_VARIABLES gid
|
||||
#define BUFLEN NSS_BUFLEN_GROUP
|
||||
+#define DEEPCOPY_FN __copy_grp
|
||||
+#define MERGE_FN __merge_grp
|
||||
|
||||
#include <nss/getXXbyYY_r.c>
|
||||
diff --git a/grp/getgrnam_r.c b/grp/getgrnam_r.c
|
||||
index 0061cb2f7e0bd311d19775e49eb3fdd8a93447f1..c5535f4057ddfc40965f27789c34345045c8bf3b 100644
|
||||
--- a/grp/getgrnam_r.c
|
||||
+++ b/grp/getgrnam_r.c
|
||||
@@ -16,13 +16,17 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <grp.h>
|
||||
|
||||
+#include "grp-merge.h"
|
||||
|
||||
#define LOOKUP_TYPE struct group
|
||||
#define FUNCTION_NAME getgrnam
|
||||
#define DATABASE_NAME group
|
||||
#define ADD_PARAMS const char *name
|
||||
#define ADD_VARIABLES name
|
||||
|
||||
+#define DEEPCOPY_FN __copy_grp
|
||||
+#define MERGE_FN __merge_grp
|
||||
+
|
||||
#include <nss/getXXbyYY_r.c>
|
||||
diff --git a/grp/grp-merge.c b/grp/grp-merge.c
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ca959dbfe403c89d6f3184f2b361b0c6488c9182
|
||||
--- /dev/null
|
||||
+++ b/grp/grp-merge.c
|
||||
@@ -0,0 +1,178 @@
|
||||
+/* Group merging implementation.
|
||||
+ Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <grp.h>
|
||||
+#include "grp-merge.h"
|
||||
+
|
||||
+#define BUFCHECK(size) \
|
||||
+ do { \
|
||||
+ if (c + size > buflen) \
|
||||
+ { \
|
||||
+ free (members); \
|
||||
+ return ERANGE; \
|
||||
+ } \
|
||||
+ } while(0)
|
||||
+
|
||||
+int
|
||||
+__copy_grp (const struct group srcgrp, const size_t buflen,
|
||||
+ struct group *destgrp, char *destbuf, char **endptr)
|
||||
+{
|
||||
+ size_t i;
|
||||
+ size_t c = 0;
|
||||
+ size_t len;
|
||||
+ size_t memcount;
|
||||
+ char **members = NULL;
|
||||
+
|
||||
+ /* Copy the GID. */
|
||||
+ destgrp->gr_gid = srcgrp.gr_gid;
|
||||
+
|
||||
+ /* Copy the name. */
|
||||
+ len = strlen (srcgrp.gr_name) + 1;
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&destbuf[c], srcgrp.gr_name, len);
|
||||
+ destgrp->gr_name = &destbuf[c];
|
||||
+ c += len;
|
||||
+
|
||||
+ /* Copy the password. */
|
||||
+ len = strlen (srcgrp.gr_passwd) + 1;
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&destbuf[c], srcgrp.gr_passwd, len);
|
||||
+ destgrp->gr_passwd = &destbuf[c];
|
||||
+ c += len;
|
||||
+
|
||||
+ /* Count all of the members. */
|
||||
+ for (memcount = 0; srcgrp.gr_mem[memcount]; memcount++)
|
||||
+ ;
|
||||
+
|
||||
+ /* Allocate a temporary holding area for the pointers to the member
|
||||
+ contents, including space for a NULL-terminator. */
|
||||
+ members = malloc (sizeof (char *) * (memcount + 1));
|
||||
+ if (members == NULL)
|
||||
+ return ENOMEM;
|
||||
+
|
||||
+ /* Copy all of the group members to destbuf and add a pointer to each of
|
||||
+ them into the 'members' array. */
|
||||
+ for (i = 0; srcgrp.gr_mem[i]; i++)
|
||||
+ {
|
||||
+ len = strlen (srcgrp.gr_mem[i]) + 1;
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&destbuf[c], srcgrp.gr_mem[i], len);
|
||||
+ members[i] = &destbuf[c];
|
||||
+ c += len;
|
||||
+ }
|
||||
+ members[i] = NULL;
|
||||
+
|
||||
+ /* Copy the pointers from the members array into the buffer and assign them
|
||||
+ to the gr_mem member of destgrp. */
|
||||
+ destgrp->gr_mem = (char **) &destbuf[c];
|
||||
+ len = sizeof (char *) * (memcount + 1);
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&destbuf[c], members, len);
|
||||
+ c += len;
|
||||
+ free (members);
|
||||
+ members = NULL;
|
||||
+
|
||||
+ /* Save the count of members at the end. */
|
||||
+ BUFCHECK (sizeof (size_t));
|
||||
+ memcpy (&destbuf[c], &memcount, sizeof (size_t));
|
||||
+ c += sizeof (size_t);
|
||||
+
|
||||
+ if (endptr)
|
||||
+ *endptr = destbuf + c;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Check that the name, GID and passwd fields match, then
|
||||
+ copy in the gr_mem array. */
|
||||
+int
|
||||
+__merge_grp (struct group *savedgrp, char *savedbuf, char *savedend,
|
||||
+ size_t buflen, struct group *mergegrp, char *mergebuf)
|
||||
+{
|
||||
+ size_t c, i, len;
|
||||
+ size_t savedmemcount;
|
||||
+ size_t memcount;
|
||||
+ size_t membersize;
|
||||
+ char **members = NULL;
|
||||
+
|
||||
+ /* We only support merging members of groups with identical names and
|
||||
+ GID values. If we hit this case, we need to overwrite the current
|
||||
+ buffer with the saved one (which is functionally equivalent to
|
||||
+ treating the new lookup as NSS_STATUS NOTFOUND. */
|
||||
+ if (mergegrp->gr_gid != savedgrp->gr_gid
|
||||
+ || strcmp (mergegrp->gr_name, savedgrp->gr_name))
|
||||
+ return __copy_grp (*savedgrp, buflen, mergegrp, mergebuf, NULL);
|
||||
+
|
||||
+ /* Get the count of group members from the last sizeof (size_t) bytes in the
|
||||
+ mergegrp buffer. */
|
||||
+ savedmemcount = (size_t) *(savedend - sizeof (size_t));
|
||||
+
|
||||
+ /* Get the count of new members to add. */
|
||||
+ for (memcount = 0; mergegrp->gr_mem[memcount]; memcount++)
|
||||
+ ;
|
||||
+
|
||||
+ /* Create a temporary array to hold the pointers to the member values from
|
||||
+ both the saved and merge groups. */
|
||||
+ membersize = savedmemcount + memcount + 1;
|
||||
+ members = malloc (sizeof (char *) * membersize);
|
||||
+ if (members == NULL)
|
||||
+ return ENOMEM;
|
||||
+
|
||||
+ /* Copy in the existing member pointers from the saved group
|
||||
+ Note: this is not NULL-terminated yet. */
|
||||
+ memcpy (members, savedgrp->gr_mem, sizeof (char *) * savedmemcount);
|
||||
+
|
||||
+ /* Back up into the savedbuf until we get back to the NULL-terminator of the
|
||||
+ group member list. (This means walking back savedmemcount + 1 (char *) pointers
|
||||
+ and the member count value.
|
||||
+ The value of c is going to be the used length of the buffer backed up by
|
||||
+ the member count and further backed up by the size of the pointers. */
|
||||
+ c = savedend - savedbuf
|
||||
+ - sizeof (size_t)
|
||||
+ - sizeof (char *) * (savedmemcount + 1);
|
||||
+
|
||||
+ /* Add all the new group members, overwriting the old NULL-terminator while
|
||||
+ adding the new pointers to the temporary array. */
|
||||
+ for (i = 0; mergegrp->gr_mem[i]; i++)
|
||||
+ {
|
||||
+ len = strlen (mergegrp->gr_mem[i]) + 1;
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&savedbuf[c], mergegrp->gr_mem[i], len);
|
||||
+ members[savedmemcount + i] = &savedbuf[c];
|
||||
+ c += len;
|
||||
+ }
|
||||
+ /* Add the NULL-terminator. */
|
||||
+ members[savedmemcount + memcount] = NULL;
|
||||
+
|
||||
+ /* Copy the member array back into the buffer after the member list and free
|
||||
+ the member array. */
|
||||
+ savedgrp->gr_mem = (char **) &savedbuf[c];
|
||||
+ len = sizeof (char *) * membersize;
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&savedbuf[c], members, len);
|
||||
+ c += len;
|
||||
+
|
||||
+ free (members);
|
||||
+ members = NULL;
|
||||
+
|
||||
+ /* Finally, copy the results back into mergebuf, since that's the buffer
|
||||
+ that we were provided by the caller. */
|
||||
+ return __copy_grp (*savedgrp, buflen, mergegrp, mergebuf, NULL);
|
||||
+}
|
||||
diff --git a/grp/grp-merge.h b/grp/grp-merge.h
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..59013487d0d907c76521ab504e265077937bfb5e
|
||||
--- /dev/null
|
||||
+++ b/grp/grp-merge.h
|
||||
@@ -0,0 +1,35 @@
|
||||
+/* Group merging implementation.
|
||||
+ Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef _GRP_MERGE_H
|
||||
+#define _GRP_MERGE_H 1
|
||||
+
|
||||
+#include <grp.h>
|
||||
+
|
||||
+/* Duplicate a grp struct (and its members). When no longer needed, the
|
||||
+ calling function must free(newbuf). */
|
||||
+int
|
||||
+__copy_grp (const struct group srcgrp, const size_t buflen,
|
||||
+ struct group *destgrp, char *destbuf, char **endptr);
|
||||
+
|
||||
+/* Merge the member lists of two grp structs together. */
|
||||
+int
|
||||
+__merge_grp (struct group *savedgrp, char *savedbuf, char *savedend,
|
||||
+ size_t buflen, struct group *mergegrp, char *mergebuf);
|
||||
+
|
||||
+#endif /* _GRP_MERGE_H */
|
||||
diff --git a/manual/nss.texi b/manual/nss.texi
|
||||
index 66dcceffe01f225f078e88dd006bb90e80c85723..95e3544bcd97995720e7154ec43df4090154bf4c 100644
|
||||
--- a/manual/nss.texi
|
||||
+++ b/manual/nss.texi
|
||||
@@ -178,11 +178,11 @@ where
|
||||
@var{action} @result{} return | continue
|
||||
@end smallexample
|
||||
|
||||
The case of the keywords is insignificant. The @var{status}
|
||||
values are the results of a call to a lookup function of a specific
|
||||
-service. They mean
|
||||
+service. They mean:
|
||||
|
||||
@ftable @samp
|
||||
@item success
|
||||
No error occurred and the wanted entry is returned. The default action
|
||||
for this is @code{return}.
|
||||
@@ -202,10 +202,54 @@ The service is temporarily unavailable. This could mean a file is
|
||||
locked or a server currently cannot accept more connections. The
|
||||
default action is @code{continue}.
|
||||
@end ftable
|
||||
|
||||
@noindent
|
||||
+The @var{action} values mean:
|
||||
+
|
||||
+@ftable @samp
|
||||
+@item return
|
||||
+
|
||||
+If the status matches, stop the lookup process at this service
|
||||
+specification. If an entry is available, provide it to the application.
|
||||
+If an error occurred, report it to the application. In case of a prior
|
||||
+@samp{merge} action, the data is combined with previous lookup results,
|
||||
+as explained below.
|
||||
+
|
||||
+@item continue
|
||||
+
|
||||
+If the status matches, proceed with the lookup process at the next
|
||||
+entry, discarding the result of the current lookup (and any merged
|
||||
+data). An exception is the @samp{initgroups} database and the
|
||||
+@samp{success} status, where @samp{continue} acts like @code{merge}
|
||||
+below.
|
||||
+
|
||||
+@item merge
|
||||
+
|
||||
+Proceed with the lookup process, retaining the current lookup result.
|
||||
+This action is useful only with the @samp{success} status. If a
|
||||
+subsequent service lookup succeeds and has a matching @samp{return}
|
||||
+specification, the results are merged, the lookup process ends, and the
|
||||
+merged results are returned to the application. If the following service
|
||||
+has a matching @samp{merge} action, the lookup process continues,
|
||||
+retaining the combined data from this and any previous lookups.
|
||||
+
|
||||
+After a @code{merge} action, errors from subsequent lookups are ignored,
|
||||
+and the data gathered so far will be returned.
|
||||
+
|
||||
+The @samp{merge} only applies to the @samp{success} status. It is
|
||||
+currently implemented for the @samp{group} database and its group
|
||||
+members field, @samp{gr_mem}. If specified for other databases, it
|
||||
+causes the lookup to fail (if the @var{status} matches).
|
||||
+
|
||||
+When processing @samp{merge} for @samp{group} membership, the group GID
|
||||
+and name must be identical for both entries. If only one or the other is
|
||||
+a match, the behavior is undefined.
|
||||
+
|
||||
+@end ftable
|
||||
+
|
||||
+@noindent
|
||||
If we have a line like
|
||||
|
||||
@smallexample
|
||||
ethers: nisplus [NOTFOUND=return] db files
|
||||
@end smallexample
|
||||
diff --git a/nscd/Makefile b/nscd/Makefile
|
||||
index e1a1aa92fc699aa132f7192da49f698a078e5910..3e6895573ae33221c728617f4c95bb3e8c5d5c47 100644
|
||||
--- a/nscd/Makefile
|
||||
+++ b/nscd/Makefile
|
||||
@@ -29,16 +29,19 @@ aux := nscd_helper
|
||||
endif
|
||||
|
||||
# To find xmalloc.c
|
||||
vpath %.c ../locale/programs
|
||||
|
||||
+# To find grp-merge.c
|
||||
+vpath %.c ../grp
|
||||
+
|
||||
nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \
|
||||
getgrnam_r getgrgid_r hstcache gethstbyad_r gethstbynm3_r \
|
||||
getsrvbynm_r getsrvbypt_r servicescache \
|
||||
dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \
|
||||
xmalloc xstrdup aicache initgrcache gai res_hconf \
|
||||
- netgroupcache
|
||||
+ netgroupcache grp-merge
|
||||
|
||||
ifeq ($(build-nscd)$(have-thread-library),yesyes)
|
||||
|
||||
others += nscd
|
||||
others-pie += nscd
|
||||
diff --git a/nscd/getgrgid_r.c b/nscd/getgrgid_r.c
|
||||
index fe5bda424169d56f642f125ef1f2df77a84de221..25de4a3b0b74841c44844a0541cf4d2365b22515 100644
|
||||
--- a/nscd/getgrgid_r.c
|
||||
+++ b/nscd/getgrgid_r.c
|
||||
@@ -15,17 +15,21 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <grp.h>
|
||||
|
||||
+#include "grp/grp-merge.h"
|
||||
|
||||
#define LOOKUP_TYPE struct group
|
||||
#define FUNCTION_NAME getgrgid
|
||||
#define DATABASE_NAME group
|
||||
#define ADD_PARAMS gid_t gid
|
||||
#define ADD_VARIABLES gid
|
||||
#define BUFLEN NSS_BUFLEN_GROUP
|
||||
|
||||
+#define DEEPCOPY_FN __copy_grp
|
||||
+#define MERGE_FN __merge_grp
|
||||
+
|
||||
/* We are nscd, so we don't want to be talking to ourselves. */
|
||||
#undef USE_NSCD
|
||||
|
||||
#include <nss/getXXbyYY_r.c>
|
||||
diff --git a/nscd/getgrnam_r.c b/nscd/getgrnam_r.c
|
||||
index 5ec56877f5798ca34c2e0074d5093cc22b6d58dc..386d66c5832ffee68e95195f6e34b723f41d0984 100644
|
||||
--- a/nscd/getgrnam_r.c
|
||||
+++ b/nscd/getgrnam_r.c
|
||||
@@ -15,16 +15,20 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <grp.h>
|
||||
|
||||
+#include "grp/grp-merge.h"
|
||||
|
||||
#define LOOKUP_TYPE struct group
|
||||
#define FUNCTION_NAME getgrnam
|
||||
#define DATABASE_NAME group
|
||||
#define ADD_PARAMS const char *name
|
||||
#define ADD_VARIABLES name
|
||||
|
||||
+#define DEEPCOPY_FN __copy_grp
|
||||
+#define MERGE_FN __merge_grp
|
||||
+
|
||||
/* We are nscd, so we don't want to be talking to ourselves. */
|
||||
#undef USE_NSCD
|
||||
|
||||
#include <nss/getXXbyYY_r.c>
|
||||
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
|
||||
index 198f8cfebd51be9c738f03f950f093b0855ab3cb..5f49ae8b828fce6dc30c7ccc9606319bffc52d5b 100644
|
||||
--- a/nss/getXXbyYY_r.c
|
||||
+++ b/nss/getXXbyYY_r.c
|
||||
@@ -129,10 +129,52 @@
|
||||
# define AF_VAL af
|
||||
#else
|
||||
# define AF_VAL AF_INET
|
||||
#endif
|
||||
|
||||
+
|
||||
+/* Set defaults for merge functions that haven't been defined. */
|
||||
+#ifndef DEEPCOPY_FN
|
||||
+static inline int
|
||||
+__copy_einval (LOOKUP_TYPE a,
|
||||
+ const size_t b,
|
||||
+ LOOKUP_TYPE *c,
|
||||
+ char *d,
|
||||
+ char **e)
|
||||
+{
|
||||
+ return EINVAL;
|
||||
+}
|
||||
+# define DEEPCOPY_FN __copy_einval
|
||||
+#endif
|
||||
+
|
||||
+#ifndef MERGE_FN
|
||||
+static inline int
|
||||
+__merge_einval (LOOKUP_TYPE *a,
|
||||
+ char *b,
|
||||
+ char *c,
|
||||
+ size_t d,
|
||||
+ LOOKUP_TYPE *e,
|
||||
+ char *f)
|
||||
+{
|
||||
+ return EINVAL;
|
||||
+}
|
||||
+# define MERGE_FN __merge_einval
|
||||
+#endif
|
||||
+
|
||||
+#define CHECK_MERGE(err, status) \
|
||||
+do { \
|
||||
+ if (err) \
|
||||
+ { \
|
||||
+ __set_errno (err); \
|
||||
+ if (err == ERANGE) \
|
||||
+ status = NSS_STATUS_TRYAGAIN; \
|
||||
+ else \
|
||||
+ status = NSS_STATUS_UNAVAIL; \
|
||||
+ break; \
|
||||
+ } \
|
||||
+} while(0)
|
||||
+
|
||||
/* Type of the lookup function we need here. */
|
||||
typedef enum nss_status (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *,
|
||||
size_t, int * H_ERRNO_PARM
|
||||
EXTRA_PARAMS);
|
||||
|
||||
@@ -150,17 +192,20 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||||
{
|
||||
static bool startp_initialized;
|
||||
static service_user *startp;
|
||||
static lookup_function start_fct;
|
||||
service_user *nip;
|
||||
+ int do_merge = 0;
|
||||
+ LOOKUP_TYPE mergegrp;
|
||||
+ char *mergebuf = NULL;
|
||||
+ char *endptr = NULL;
|
||||
union
|
||||
{
|
||||
lookup_function l;
|
||||
void *ptr;
|
||||
} fct;
|
||||
-
|
||||
- int no_more;
|
||||
+ int no_more, err;
|
||||
enum nss_status status = NSS_STATUS_UNAVAIL;
|
||||
#ifdef USE_NSCD
|
||||
int nscd_status;
|
||||
#endif
|
||||
#ifdef NEED_H_ERRNO
|
||||
@@ -276,13 +321,69 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||||
&& *h_errnop == NETDB_INTERNAL
|
||||
#endif
|
||||
&& errno == ERANGE)
|
||||
break;
|
||||
|
||||
+ if (do_merge)
|
||||
+ {
|
||||
+
|
||||
+ if (status == NSS_STATUS_SUCCESS)
|
||||
+ {
|
||||
+ /* The previous loop saved a buffer for merging.
|
||||
+ Perform the merge now. */
|
||||
+ err = MERGE_FN (&mergegrp, mergebuf, endptr, buflen, resbuf,
|
||||
+ buffer);
|
||||
+ CHECK_MERGE (err,status);
|
||||
+ do_merge = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* If the result wasn't SUCCESS, copy the saved buffer back
|
||||
+ into the result buffer and set the status back to
|
||||
+ NSS_STATUS_SUCCESS to match the previous pass through the loop.
|
||||
+ * If the next action is CONTINUE, it will overwrite the value
|
||||
+ currently in the buffer and return the new value.
|
||||
+ * If the next action is RETURN, we'll return the previously-
|
||||
+ acquired values.
|
||||
+ * If the next action is MERGE, then it will be added to the buffer
|
||||
+ saved from the previous source. */
|
||||
+ err = DEEPCOPY_FN (mergegrp, buflen, resbuf, buffer, NULL);
|
||||
+ CHECK_MERGE (err, status);
|
||||
+ status = NSS_STATUS_SUCCESS;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If we were are configured to merge this value with the next one,
|
||||
+ save the current value of the group struct. */
|
||||
+ if (nss_next_action (nip, status) == NSS_ACTION_MERGE
|
||||
+ && status == NSS_STATUS_SUCCESS)
|
||||
+ {
|
||||
+ /* Copy the current values into a buffer to be merged with the next
|
||||
+ set of retrieved values. */
|
||||
+ if (!mergebuf)
|
||||
+ {
|
||||
+ /* Only allocate once and reuse it for as many merges as we need
|
||||
+ to perform. */
|
||||
+ mergebuf = malloc (buflen);
|
||||
+ if (!mergebuf)
|
||||
+ {
|
||||
+ __set_errno (ENOMEM);
|
||||
+ status = NSS_STATUS_UNAVAIL;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ err = DEEPCOPY_FN (*resbuf, buflen, &mergegrp, mergebuf, &endptr);
|
||||
+ CHECK_MERGE (err, status);
|
||||
+ do_merge = 1;
|
||||
+ }
|
||||
+
|
||||
no_more = __nss_next2 (&nip, REENTRANT_NAME_STRING,
|
||||
REENTRANT2_NAME_STRING, &fct.ptr, status, 0);
|
||||
}
|
||||
+ free(mergebuf);
|
||||
+ mergebuf = NULL;
|
||||
|
||||
#ifdef HANDLE_DIGITS_DOTS
|
||||
done:
|
||||
#endif
|
||||
*result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
|
||||
diff --git a/nss/getnssent_r.c b/nss/getnssent_r.c
|
||||
index f5b903671ca53ccad108eeb4e49ea40a45fa5cdf..c0743436f661d4d83045a6353b49291a4c0f220b 100644
|
||||
--- a/nss/getnssent_r.c
|
||||
+++ b/nss/getnssent_r.c
|
||||
@@ -77,11 +77,25 @@ __nss_setent (const char *func_name, db_lookup_function lookup_fct,
|
||||
if (stayopen_tmp)
|
||||
status = DL_CALL_FCT (fct.f, (*stayopen_tmp));
|
||||
else
|
||||
status = DL_CALL_FCT (fct.f, (0));
|
||||
|
||||
- no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, status, 0);
|
||||
+ if (nss_next_action (*nip, status) == NSS_ACTION_MERGE)
|
||||
+ {
|
||||
+ /* This is a special-case. When [SUCCESS=merge] is in play,
|
||||
+ _nss_next2() will skip to the next database. Due to the
|
||||
+ implementation of that function, we can't know whether we're
|
||||
+ in an enumeration or an individual lookup, which behaves
|
||||
+ differently with regards to merging. We'll treat SUCCESS as
|
||||
+ an indication to start the enumeration at this database. */
|
||||
+ no_more = 1;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, status, 0);
|
||||
+ }
|
||||
+
|
||||
if (is_last_nip)
|
||||
*last_nip = *nip;
|
||||
}
|
||||
|
||||
if (stayopen_tmp)
|
||||
@@ -173,12 +187,26 @@ __nss_getent_r (const char *getent_func_name,
|
||||
&& errno == ERANGE)
|
||||
break;
|
||||
|
||||
do
|
||||
{
|
||||
- no_more = __nss_next2 (nip, getent_func_name, NULL, &fct.ptr,
|
||||
- status, 0);
|
||||
+ if (status == NSS_STATUS_SUCCESS
|
||||
+ && nss_next_action (*nip, status) == NSS_ACTION_MERGE)
|
||||
+ {
|
||||
+ /* This is a special-case. When [SUCCESS=merge] is in play,
|
||||
+ _nss_next2() will skip to the next database. Due to the
|
||||
+ implementation of that function, we can't know whether we're
|
||||
+ in an enumeration or an individual lookup, which behaves
|
||||
+ differently with regards to merging. We'll treat SUCCESS as
|
||||
+ an indication to return the results here. */
|
||||
+ no_more = 1;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ no_more = __nss_next2 (nip, getent_func_name, NULL, &fct.ptr,
|
||||
+ status, 0);
|
||||
+ }
|
||||
|
||||
if (is_last_nip)
|
||||
*last_nip = *nip;
|
||||
|
||||
if (! no_more)
|
||||
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
|
||||
index faf9d1a0d5680aa79e88b2dfeea18da371c336fb..f8f60ba05aad9a571f928a3ea7d3b14f908ccb2d 100644
|
||||
--- a/nss/nsswitch.c
|
||||
+++ b/nss/nsswitch.c
|
||||
@@ -710,10 +710,13 @@ nss_parse_service_list (const char *line)
|
||||
if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0)
|
||||
action = NSS_ACTION_RETURN;
|
||||
else if (line - name == 8
|
||||
&& __strncasecmp (name, "CONTINUE", 8) == 0)
|
||||
action = NSS_ACTION_CONTINUE;
|
||||
+ else if (line - name == 5
|
||||
+ && __strncasecmp (name, "MERGE", 5) == 0)
|
||||
+ action = NSS_ACTION_MERGE;
|
||||
else
|
||||
goto finish;
|
||||
|
||||
if (not)
|
||||
{
|
||||
diff --git a/nss/nsswitch.h b/nss/nsswitch.h
|
||||
index a5318fa82be43c8314807ad76de231e572e91c06..5bc2de3b1d82978102ac7a129c0ba5b7eb3cfd25 100644
|
||||
--- a/nss/nsswitch.h
|
||||
+++ b/nss/nsswitch.h
|
||||
@@ -30,11 +30,12 @@
|
||||
|
||||
/* Actions performed after lookup finished. */
|
||||
typedef enum
|
||||
{
|
||||
NSS_ACTION_CONTINUE,
|
||||
- NSS_ACTION_RETURN
|
||||
+ NSS_ACTION_RETURN,
|
||||
+ NSS_ACTION_MERGE
|
||||
} lookup_actions;
|
||||
|
||||
|
||||
typedef struct service_library
|
||||
{
|
987
glibc-pthread-barrier.patch
Normal file
987
glibc-pthread-barrier.patch
Normal file
@ -0,0 +1,987 @@
|
||||
Short description: New pthread_barrier algorithm to fulfill barrier destruction requirements.
|
||||
Author(s): Torvald Riegel <triegel@redhat.com>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: NA
|
||||
Bug-Fedora: NA
|
||||
Bug-Upstream: #13065
|
||||
Upstream status: http://patchwork.sourceware.org/patch/10062/
|
||||
# commit d6533b39f004789e0de4b7d58a29f8282ee95f7b
|
||||
# Author: Torvald Riegel <triegel@redhat.com>
|
||||
# Date: Wed Jun 24 14:37:32 2015 +0200
|
||||
#
|
||||
# New pthread_barrier algorithm to fulfill barrier destruction requirements.
|
||||
#
|
||||
# The previous barrier implementation did not fulfill the POSIX requirements
|
||||
# for when a barrier can be destroyed. Specifically, it was possible that
|
||||
# threads that haven't noticed yet that their round is complete still access
|
||||
# the barrier's memory, and that those accesses can happen after the barrier
|
||||
# has been legally destroyed.
|
||||
# The new algorithm does not have this issue, and it avoids using a lock
|
||||
# internally.
|
||||
#
|
||||
Index: glibc-2.22-621-g90c400b/nptl/Makefile
|
||||
===================================================================
|
||||
--- glibc-2.22-621-g90c400b.orig/nptl/Makefile
|
||||
+++ glibc-2.22-621-g90c400b/nptl/Makefile
|
||||
@@ -243,7 +243,7 @@ tests = tst-typesizes \
|
||||
tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
|
||||
tst-sem8 tst-sem9 tst-sem10 tst-sem11 tst-sem12 tst-sem13 tst-sem14 \
|
||||
tst-sem15 \
|
||||
- tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
|
||||
+ tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 tst-barrier5 \
|
||||
tst-align tst-align3 \
|
||||
tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
|
||||
tst-basic7 \
|
||||
@@ -304,7 +304,7 @@ tests-nolibpthread = tst-unload
|
||||
|
||||
gen-as-const-headers = pthread-errnos.sym \
|
||||
lowlevelcond.sym lowlevelrwlock.sym \
|
||||
- lowlevelbarrier.sym unwindbuf.sym \
|
||||
+ unwindbuf.sym \
|
||||
lowlevelrobustlock.sym pthread-pi-defines.sym
|
||||
|
||||
|
||||
Index: glibc-2.22-621-g90c400b/nptl/lowlevelbarrier.sym
|
||||
===================================================================
|
||||
--- glibc-2.22-621-g90c400b.orig/nptl/lowlevelbarrier.sym
|
||||
+++ /dev/null
|
||||
@@ -1,12 +0,0 @@
|
||||
-#include <stddef.h>
|
||||
-#include <sched.h>
|
||||
-#include <bits/pthreadtypes.h>
|
||||
-#include "internaltypes.h"
|
||||
-
|
||||
---
|
||||
-
|
||||
-CURR_EVENT offsetof (struct pthread_barrier, curr_event)
|
||||
-MUTEX offsetof (struct pthread_barrier, lock)
|
||||
-LEFT offsetof (struct pthread_barrier, left)
|
||||
-INIT_COUNT offsetof (struct pthread_barrier, init_count)
|
||||
-PRIVATE offsetof (struct pthread_barrier, private)
|
||||
Index: glibc-2.22-621-g90c400b/nptl/pthread_barrier_destroy.c
|
||||
===================================================================
|
||||
--- glibc-2.22-621-g90c400b.orig/nptl/pthread_barrier_destroy.c
|
||||
+++ glibc-2.22-621-g90c400b/nptl/pthread_barrier_destroy.c
|
||||
@@ -18,25 +18,44 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include "pthreadP.h"
|
||||
-#include <lowlevellock.h>
|
||||
+#include <atomic.h>
|
||||
+#include <futex-internal.h>
|
||||
|
||||
|
||||
int
|
||||
pthread_barrier_destroy (pthread_barrier_t *barrier)
|
||||
{
|
||||
- struct pthread_barrier *ibarrier;
|
||||
- int result = EBUSY;
|
||||
+ struct pthread_barrier *bar = (struct pthread_barrier *) barrier;
|
||||
|
||||
- ibarrier = (struct pthread_barrier *) barrier;
|
||||
+ /* Destroying a barrier is only allowed if no thread is blocked on it.
|
||||
+ Thus, there is no unfinished round, and all modifications to IN will
|
||||
+ have happened before us (either because the calling thread took part
|
||||
+ in the most recent round and thus synchronized-with all other threads
|
||||
+ entering, or the program ensured this through other synchronization).
|
||||
+ We must wait until all threads that entered so far have confirmed that
|
||||
+ they have exited as well. To get the notification, pretend that we have
|
||||
+ reached the reset threshold. */
|
||||
+ unsigned int count = bar->count;
|
||||
+ unsigned int max_in_before_reset = BARRIER_IN_THRESHOLD
|
||||
+ - BARRIER_IN_THRESHOLD % count;
|
||||
+ /* Relaxed MO sufficient because the program must have ensured that all
|
||||
+ modifications happen-before this load (see above). */
|
||||
+ unsigned int in = atomic_load_relaxed (&bar->in);
|
||||
+ /* Trigger reset. The required acquire MO is below. */
|
||||
+ if (atomic_fetch_add_relaxed (&bar->out, max_in_before_reset - in) < in)
|
||||
+ {
|
||||
+ /* Not all threads confirmed yet that they have exited, so another
|
||||
+ thread will perform a reset. Wait until that has happened. */
|
||||
+ while (in != 0)
|
||||
+ {
|
||||
+ futex_wait_simple (&bar->in, in, bar->shared);
|
||||
+ in = atomic_load_relaxed (&bar->in);
|
||||
+ }
|
||||
+ }
|
||||
+ /* We must ensure that memory reuse happens after all prior use of the
|
||||
+ barrier (specifically, synchronize-with the reset of the barrier or the
|
||||
+ confirmation of threads leaving the barrier). */
|
||||
+ atomic_thread_fence_acquire ();
|
||||
|
||||
- lll_lock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG);
|
||||
-
|
||||
- if (__glibc_likely (ibarrier->left == ibarrier->init_count))
|
||||
- /* The barrier is not used anymore. */
|
||||
- result = 0;
|
||||
- else
|
||||
- /* Still used, return with an error. */
|
||||
- lll_unlock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG);
|
||||
-
|
||||
- return result;
|
||||
+ return 0;
|
||||
}
|
||||
Index: glibc-2.22-621-g90c400b/nptl/pthread_barrier_init.c
|
||||
===================================================================
|
||||
--- glibc-2.22-621-g90c400b.orig/nptl/pthread_barrier_init.c
|
||||
+++ glibc-2.22-621-g90c400b/nptl/pthread_barrier_init.c
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include "pthreadP.h"
|
||||
-#include <lowlevellock.h>
|
||||
+#include <futex-internal.h>
|
||||
#include <kernel-features.h>
|
||||
|
||||
|
||||
@@ -34,8 +34,10 @@ __pthread_barrier_init (pthread_barrier_
|
||||
{
|
||||
struct pthread_barrier *ibarrier;
|
||||
|
||||
- /* XXX EINVAL is not specified by POSIX as a possible error code. */
|
||||
- if (__glibc_unlikely (count == 0))
|
||||
+ /* XXX EINVAL is not specified by POSIX as a possible error code. See
|
||||
+ pthread_barrier_wait for the reason for the comparison with
|
||||
+ BARRIER_IN_THRESHOLD. */
|
||||
+ if (__glibc_unlikely (count == 0 || count >= BARRIER_IN_THRESHOLD))
|
||||
return EINVAL;
|
||||
|
||||
const struct pthread_barrierattr *iattr
|
||||
@@ -46,15 +48,12 @@ __pthread_barrier_init (pthread_barrier_
|
||||
ibarrier = (struct pthread_barrier *) barrier;
|
||||
|
||||
/* Initialize the individual fields. */
|
||||
- ibarrier->lock = LLL_LOCK_INITIALIZER;
|
||||
- ibarrier->left = count;
|
||||
- ibarrier->init_count = count;
|
||||
- ibarrier->curr_event = 0;
|
||||
-
|
||||
- /* XXX Don't use FUTEX_SHARED or FUTEX_PRIVATE as long as there are still
|
||||
- assembly implementations that expect the value determined below. */
|
||||
- ibarrier->private = (iattr->pshared != PTHREAD_PROCESS_PRIVATE
|
||||
- ? 0 : FUTEX_PRIVATE_FLAG);
|
||||
+ ibarrier->in = 0;
|
||||
+ ibarrier->out = 0;
|
||||
+ ibarrier->count = count;
|
||||
+ ibarrier->current_round = 0;
|
||||
+ ibarrier->shared = (iattr->pshared == PTHREAD_PROCESS_PRIVATE
|
||||
+ ? FUTEX_PRIVATE : FUTEX_SHARED);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Index: glibc-2.22-621-g90c400b/nptl/pthread_barrier_wait.c
|
||||
===================================================================
|
||||
--- glibc-2.22-621-g90c400b.orig/nptl/pthread_barrier_wait.c
|
||||
+++ glibc-2.22-621-g90c400b/nptl/pthread_barrier_wait.c
|
||||
@@ -18,63 +18,206 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <sysdep.h>
|
||||
-#include <lowlevellock.h>
|
||||
#include <futex-internal.h>
|
||||
#include <pthreadP.h>
|
||||
|
||||
|
||||
-/* Wait on barrier. */
|
||||
+/* Wait on the barrier.
|
||||
+
|
||||
+ In each round, we wait for a fixed number of threads to enter the barrier
|
||||
+ (COUNT). Once that has happened, exactly these threads are allowed to
|
||||
+ leave the barrier. Note that POSIX does not require that only COUNT
|
||||
+ threads can attempt to block using the barrier concurrently.
|
||||
+
|
||||
+ We count the number of threads that have entered (IN). Each thread
|
||||
+ increments IN when entering, thus getting a position in the sequence of
|
||||
+ threads that are or have been waiting (starting with 1, so the position
|
||||
+ is the number of threads that have entered so far including the current
|
||||
+ thread).
|
||||
+ CURRENT_ROUND designates the most recent thread whose round has been
|
||||
+ detected as complete. When a thread detects that enough threads have
|
||||
+ entered to make a round complete, it finishes this round by effectively
|
||||
+ adding COUNT to CURRENT_ROUND atomically. Threads that believe that their
|
||||
+ round is not complete yet wait until CURRENT_ROUND is not smaller than
|
||||
+ their position anymore.
|
||||
+
|
||||
+ A barrier can be destroyed as soon as no threads are blocked on the
|
||||
+ barrier. This is already the case if just one thread from the last round
|
||||
+ has stopped waiting and returned to the caller; the assumption is that
|
||||
+ all threads from the round are unblocked atomically, even though they may
|
||||
+ return at different times from the respective calls to
|
||||
+ pthread_barrier_wait). Thus, a valid call to pthread_barrier_destroy can
|
||||
+ be concurrent with other threads still figuring out that their round has
|
||||
+ been completed. Therefore, threads need to confirm that they have left
|
||||
+ the barrier by incrementing OUT, and pthread_barrier_destroy needs to wait
|
||||
+ until OUT equals IN.
|
||||
+
|
||||
+ To avoid an ABA issue for futex_wait on CURRENT_ROUND and for archs with
|
||||
+ 32b-only atomics, we additionally reset the barrier when IN reaches
|
||||
+ a threshold to avoid overflow. We assume that the total number of threads
|
||||
+ is less than INT_MAX/2, and set the threshold accordingly so that we can
|
||||
+ use a simple atomic_fetch_add on IN instead of a CAS when entering. The
|
||||
+ threshold is always set to the end of a round, so all threads that have
|
||||
+ entered are either pre-reset threads or post-reset threads (i.e., have a
|
||||
+ position larger than the threshold).
|
||||
+ Pre-reset threads just run the algorithm explained above. Post-reset
|
||||
+ threads wait until IN is reset to a pre-threshold value.
|
||||
+ When the last pre-reset thread leaves the barrier (i.e., OUT equals the
|
||||
+ threshold), it resets the barrier to its initial state. Other (post-reset)
|
||||
+ threads wait for the reset to have finished by waiting until IN is less
|
||||
+ than the threshold and then restart by trying to enter the barrier again.
|
||||
+
|
||||
+ We reuse the reset mechanism in pthread_barrier_destroy to get notified
|
||||
+ when all threads have left the barrier: We trigger an artificial reset and
|
||||
+ wait for the last pre-reset thread to finish reset, thus notifying the
|
||||
+ thread that is about to destroy the barrier.
|
||||
+
|
||||
+ Blocking using futexes is straightforward: pre-reset threads wait for
|
||||
+ completion of their round using CURRENT_ROUND as futex word, and post-reset
|
||||
+ threads and pthread_barrier_destroy use IN as futex word.
|
||||
+
|
||||
+ Further notes:
|
||||
+ * It is not simple to let some of the post-reset threads help with the
|
||||
+ reset because of the ABA issues that arise; therefore, we simply make
|
||||
+ the last thread to leave responsible for the reset.
|
||||
+ * POSIX leaves it unspecified whether a signal handler running in a thread
|
||||
+ that has been unblocked (because its round is complete) can stall all
|
||||
+ other threads and prevent them from returning from the barrier. In this
|
||||
+ implementation, other threads will return. However,
|
||||
+ pthread_barrier_destroy will of course wait for the signal handler thread
|
||||
+ to confirm that it left the barrier.
|
||||
+
|
||||
+ TODO We should add spinning with back-off. Once we do that, we could also
|
||||
+ try to avoid the futex_wake syscall when a round is detected as finished.
|
||||
+ If we do not spin, it is quite likely that at least some other threads will
|
||||
+ have called futex_wait already. */
|
||||
int
|
||||
__pthread_barrier_wait (pthread_barrier_t *barrier)
|
||||
{
|
||||
- struct pthread_barrier *ibarrier = (struct pthread_barrier *) barrier;
|
||||
- int result = 0;
|
||||
- int lll_private = ibarrier->private ^ FUTEX_PRIVATE_FLAG;
|
||||
- int futex_private = (lll_private == LLL_PRIVATE
|
||||
- ? FUTEX_PRIVATE : FUTEX_SHARED);
|
||||
+ struct pthread_barrier *bar = (struct pthread_barrier *) barrier;
|
||||
|
||||
- /* Make sure we are alone. */
|
||||
- lll_lock (ibarrier->lock, lll_private);
|
||||
+ /* How many threads entered so far, including ourself. */
|
||||
+ unsigned int i;
|
||||
|
||||
- /* One more arrival. */
|
||||
- --ibarrier->left;
|
||||
+ reset_restart:
|
||||
+ /* Try to enter the barrier. We need acquire MO to (1) ensure that if we
|
||||
+ observe that our round can be completed (see below for our attempt to do
|
||||
+ so), all pre-barrier-entry effects of all threads in our round happen
|
||||
+ before us completing the round, and (2) to make our use of the barrier
|
||||
+ happen after a potential reset. We need release MO to make sure that our
|
||||
+ pre-barrier-entry effects happen before threads in this round leaving the
|
||||
+ barrier. */
|
||||
+ i = atomic_fetch_add_acq_rel (&bar->in, 1) + 1;
|
||||
+ /* These loads are after the fetch_add so that we're less likely to first
|
||||
+ pull in the cache line as shared. */
|
||||
+ unsigned int count = bar->count;
|
||||
+ /* This is the number of threads that can enter before we need to reset.
|
||||
+ Always at the end of a round. */
|
||||
+ unsigned int max_in_before_reset = BARRIER_IN_THRESHOLD
|
||||
+ - BARRIER_IN_THRESHOLD % count;
|
||||
|
||||
- /* Are these all? */
|
||||
- if (ibarrier->left == 0)
|
||||
+ if (i > max_in_before_reset)
|
||||
{
|
||||
- /* Yes. Increment the event counter to avoid invalid wake-ups and
|
||||
- tell the current waiters that it is their turn. */
|
||||
- ++ibarrier->curr_event;
|
||||
-
|
||||
- /* Wake up everybody. */
|
||||
- futex_wake (&ibarrier->curr_event, INT_MAX, futex_private);
|
||||
+ /* We're in a reset round. Just wait for a reset to finish; do not
|
||||
+ help finishing previous rounds because this could happen
|
||||
+ concurrently with a reset. */
|
||||
+ while (i > max_in_before_reset)
|
||||
+ {
|
||||
+ futex_wait_simple (&bar->in, i, bar->shared);
|
||||
+ /* Relaxed MO is fine here because we just need an indication for
|
||||
+ when we should retry to enter (which will use acquire MO, see
|
||||
+ above). */
|
||||
+ i = atomic_load_relaxed (&bar->in);
|
||||
+ }
|
||||
+ goto reset_restart;
|
||||
+ }
|
||||
|
||||
- /* This is the thread which finished the serialization. */
|
||||
- result = PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
+ /* Look at the current round. At this point, we are just interested in
|
||||
+ whether we can complete rounds, based on the information we obtained
|
||||
+ through our acquire-MO load of IN. Nonetheless, if we notice that
|
||||
+ our round has been completed using this load, we use the acquire-MO
|
||||
+ fence below to make sure that all pre-barrier-entry effects of all
|
||||
+ threads in our round happen before us leaving the barrier. Therefore,
|
||||
+ relaxed MO is sufficient. */
|
||||
+ unsigned cr = atomic_load_relaxed (&bar->current_round);
|
||||
+
|
||||
+ /* Try to finish previous rounds and/or the current round. We simply
|
||||
+ consider just our position here and do not try to do the work of threads
|
||||
+ that entered more recently. */
|
||||
+ while (cr + count <= i)
|
||||
+ {
|
||||
+ /* Calculate the new current round based on how many threads entered.
|
||||
+ NEWCR must be larger than CR because CR+COUNT ends a round. */
|
||||
+ unsigned int newcr = i - i % count;
|
||||
+ /* Try to complete previous and/or the current round. We need release
|
||||
+ MO to propagate the happens-before that we observed through reading
|
||||
+ with acquire MO from IN to other threads. If the CAS fails, it
|
||||
+ is like the relaxed-MO load of CURRENT_ROUND above. */
|
||||
+ if (atomic_compare_exchange_weak_release (&bar->current_round, &cr,
|
||||
+ newcr))
|
||||
+ {
|
||||
+ /* Update CR with the modification we just did. */
|
||||
+ cr = newcr;
|
||||
+ /* Wake threads belonging to the rounds we just finished. We may
|
||||
+ wake more threads than necessary if more than COUNT threads try
|
||||
+ to block concurrently on the barrier, but this is not a typical
|
||||
+ use of barriers.
|
||||
+ Note that we can still access SHARED because we haven't yet
|
||||
+ confirmed to have left the barrier. */
|
||||
+ futex_wake (&bar->current_round, INT_MAX, bar->shared);
|
||||
+ /* We did as much as we could based on our position. If we advanced
|
||||
+ the current round to a round sufficient for us, do not wait for
|
||||
+ that to happen and skip the acquire fence (we already
|
||||
+ synchronize-with all other threads in our round through the
|
||||
+ initial acquire MO fetch_add of IN. */
|
||||
+ if (i <= cr)
|
||||
+ goto ready_to_leave;
|
||||
+ else
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
- else
|
||||
+
|
||||
+ /* Wait until the current round is more recent than the round we are in. */
|
||||
+ while (i > cr)
|
||||
{
|
||||
- /* The number of the event we are waiting for. The barrier's event
|
||||
- number must be bumped before we continue. */
|
||||
- unsigned int event = ibarrier->curr_event;
|
||||
-
|
||||
- /* Before suspending, make the barrier available to others. */
|
||||
- lll_unlock (ibarrier->lock, lll_private);
|
||||
-
|
||||
- /* Wait for the event counter of the barrier to change. */
|
||||
- do
|
||||
- futex_wait_simple (&ibarrier->curr_event, event, futex_private);
|
||||
- while (event == ibarrier->curr_event);
|
||||
+ /* Wait for the current round to finish. */
|
||||
+ futex_wait_simple (&bar->current_round, cr, bar->shared);
|
||||
+ /* See the fence below. */
|
||||
+ cr = atomic_load_relaxed (&bar->current_round);
|
||||
}
|
||||
|
||||
- /* Make sure the init_count is stored locally or in a register. */
|
||||
- unsigned int init_count = ibarrier->init_count;
|
||||
+ /* Our round finished. Use the acquire MO fence to synchronize-with the
|
||||
+ thread that finished the round, either through the initial load of
|
||||
+ CURRENT_ROUND above or a failed CAS in the loop above. */
|
||||
+ atomic_thread_fence_acquire ();
|
||||
+
|
||||
+ /* Now signal that we left. */
|
||||
+ unsigned int o;
|
||||
+ ready_to_leave:
|
||||
+ /* We need release MO here so that our use of the barrier happens before
|
||||
+ reset or memory reuse after pthread_barrier_destroy. */
|
||||
+ o = atomic_fetch_add_release (&bar->out, 1) + 1;
|
||||
+ if (o == max_in_before_reset)
|
||||
+ {
|
||||
+ /* Perform a reset if we are the last pre-reset thread leaving. All
|
||||
+ other threads accessing the barrier are post-reset threads and are
|
||||
+ incrementing or spinning on IN. Thus, resetting IN as the last step
|
||||
+ of reset ensures that the reset is not concurrent with actual use of
|
||||
+ the barrier. We need the acquire MO fence so that the reset happens
|
||||
+ after use of the barrier by all earlier pre-reset threads. */
|
||||
+ atomic_thread_fence_acquire ();
|
||||
+ atomic_store_relaxed (&bar->current_round, 0);
|
||||
+ atomic_store_relaxed (&bar->out, 0);
|
||||
+ /* When destroying the barrier, we wait for a reset to happen. Thus,
|
||||
+ we must load SHARED now so that this happens before the barrier is
|
||||
+ destroyed. */
|
||||
+ int shared = bar->shared;
|
||||
+ atomic_store_release (&bar->in, 0);
|
||||
+ futex_wake (&bar->in, INT_MAX, shared);
|
||||
|
||||
- /* If this was the last woken thread, unlock. */
|
||||
- if (atomic_increment_val (&ibarrier->left) == init_count)
|
||||
- /* We are done. */
|
||||
- lll_unlock (ibarrier->lock, lll_private);
|
||||
+ }
|
||||
|
||||
- return result;
|
||||
+ /* Return a special value for exactly one thread per round. */
|
||||
+ return i % count == 0 ? PTHREAD_BARRIER_SERIAL_THREAD : 0;
|
||||
}
|
||||
weak_alias (__pthread_barrier_wait, pthread_barrier_wait)
|
||||
Index: glibc-2.22-621-g90c400b/nptl/pthread_barrierattr_setpshared.c
|
||||
===================================================================
|
||||
--- glibc-2.22-621-g90c400b.orig/nptl/pthread_barrierattr_setpshared.c
|
||||
+++ glibc-2.22-621-g90c400b/nptl/pthread_barrierattr_setpshared.c
|
||||
@@ -24,15 +24,11 @@
|
||||
int
|
||||
pthread_barrierattr_setpshared (pthread_barrierattr_t *attr, int pshared)
|
||||
{
|
||||
- struct pthread_barrierattr *iattr;
|
||||
-
|
||||
int err = futex_supports_pshared (pshared);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
- iattr = (struct pthread_barrierattr *) attr;
|
||||
-
|
||||
- iattr->pshared = pshared;
|
||||
+ ((struct pthread_barrierattr *) attr)->pshared = pshared;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Index: glibc-2.22-621-g90c400b/nptl/tst-barrier4.c
|
||||
===================================================================
|
||||
--- glibc-2.22-621-g90c400b.orig/nptl/tst-barrier4.c
|
||||
+++ glibc-2.22-621-g90c400b/nptl/tst-barrier4.c
|
||||
@@ -16,7 +16,7 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
-/* This is a test for behavior not guaranteed by POSIX. */
|
||||
+/* This tests destruction of a barrier right after waiting on it. */
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
Index: glibc-2.22-621-g90c400b/nptl/tst-barrier5.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ glibc-2.22-621-g90c400b/nptl/tst-barrier5.c
|
||||
@@ -0,0 +1,145 @@
|
||||
+/* Copyright (C) 2004-2015 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* This tests the barrier reset mechanism. */
|
||||
+#include <errno.h>
|
||||
+#include <pthread.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <internaltypes.h>
|
||||
+
|
||||
+
|
||||
+static pthread_barrier_t b1;
|
||||
+static pthread_barrier_t b2;
|
||||
+
|
||||
+
|
||||
+#define N 20
|
||||
+#define ROUNDS_PER_RUN 20
|
||||
+#define START ((BARRIER_IN_THRESHOLD / N - ROUNDS_PER_RUN / 2) * N)
|
||||
+
|
||||
+static void *
|
||||
+tf (void *arg)
|
||||
+{
|
||||
+ int runs = 0;
|
||||
+
|
||||
+ while (runs++ < 30)
|
||||
+ {
|
||||
+ /* In each run, we execute a number of rounds and initialize the barrier
|
||||
+ so that we will go over the reset threshold with those rounds. */
|
||||
+ for (int rounds = 0; rounds < ROUNDS_PER_RUN; rounds++)
|
||||
+ pthread_barrier_wait (&b1);
|
||||
+
|
||||
+ if (pthread_barrier_wait (&b1) == PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
+ {
|
||||
+ pthread_barrier_destroy (&b1);
|
||||
+ if (pthread_barrier_init (&b1, NULL, N) != 0)
|
||||
+ {
|
||||
+ puts ("tf: 1st barrier_init failed");
|
||||
+ exit (1);
|
||||
+ }
|
||||
+ puts ("b1 reinitialized");
|
||||
+ /* Trigger a reset. */
|
||||
+ struct pthread_barrier *bar = (struct pthread_barrier *) &b1;
|
||||
+ bar->in = START;
|
||||
+ bar->out = START;
|
||||
+ /* We deliberately don't set bar->current_round so that we also
|
||||
+ test whether the helping for the updates of current_round
|
||||
+ works correctly. */
|
||||
+ }
|
||||
+
|
||||
+ /* Same as above, just for b2. */
|
||||
+ for (int rounds = 0; rounds < ROUNDS_PER_RUN; rounds++)
|
||||
+ pthread_barrier_wait (&b2);
|
||||
+
|
||||
+ if (pthread_barrier_wait (&b2) == PTHREAD_BARRIER_SERIAL_THREAD)
|
||||
+ {
|
||||
+ pthread_barrier_destroy (&b2);
|
||||
+ if (pthread_barrier_init (&b2, NULL, N) != 0)
|
||||
+ {
|
||||
+ puts ("tf: 2nd barrier_init failed");
|
||||
+ exit (1);
|
||||
+ }
|
||||
+ puts ("b2 reinitialized");
|
||||
+ /* Trigger a reset. See above. */
|
||||
+ struct pthread_barrier *bar = (struct pthread_barrier *) &b2;
|
||||
+ bar->in = START;
|
||||
+ bar->out = START;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ pthread_attr_t at;
|
||||
+ int cnt;
|
||||
+
|
||||
+ if (pthread_attr_init (&at) != 0)
|
||||
+ {
|
||||
+ puts ("attr_init failed");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
|
||||
+ {
|
||||
+ puts ("attr_setstacksize failed");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (pthread_barrier_init (&b1, NULL, N) != 0)
|
||||
+ {
|
||||
+ puts ("1st barrier_init failed");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (pthread_barrier_init (&b2, NULL, N) != 0)
|
||||
+ {
|
||||
+ puts ("2nd barrier_init failed");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ pthread_t th[N - 1];
|
||||
+ for (cnt = 0; cnt < N - 1; ++cnt)
|
||||
+ if (pthread_create (&th[cnt], &at, tf, NULL) != 0)
|
||||
+ {
|
||||
+ puts ("pthread_create failed");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (pthread_attr_destroy (&at) != 0)
|
||||
+ {
|
||||
+ puts ("attr_destroy failed");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ tf (NULL);
|
||||
+
|
||||
+ for (cnt = 0; cnt < N - 1; ++cnt)
|
||||
+ if (pthread_join (th[cnt], NULL) != 0)
|
||||
+ {
|
||||
+ puts ("pthread_join failed");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define TEST_FUNCTION do_test ()
|
||||
+#include "../test-skeleton.c"
|
||||
Index: glibc-2.22-621-g90c400b/sysdeps/nptl/internaltypes.h
|
||||
===================================================================
|
||||
--- glibc-2.22-621-g90c400b.orig/sysdeps/nptl/internaltypes.h
|
||||
+++ glibc-2.22-621-g90c400b/sysdeps/nptl/internaltypes.h
|
||||
@@ -95,12 +95,13 @@ struct pthread_rwlockattr
|
||||
/* Barrier data structure. */
|
||||
struct pthread_barrier
|
||||
{
|
||||
- unsigned int curr_event;
|
||||
- int lock;
|
||||
- unsigned int left;
|
||||
- unsigned int init_count;
|
||||
- int private;
|
||||
+ unsigned int in;
|
||||
+ unsigned int current_round;
|
||||
+ unsigned int count;
|
||||
+ int shared;
|
||||
+ unsigned int out;
|
||||
};
|
||||
+#define BARRIER_IN_THRESHOLD (UINT_MAX/2)
|
||||
|
||||
|
||||
/* Barrier variable attribute data structure. */
|
||||
Index: glibc-2.22-621-g90c400b/sysdeps/unix/sysv/linux/i386/pthread_barrier_wait.S
|
||||
===================================================================
|
||||
--- glibc-2.22-621-g90c400b.orig/sysdeps/unix/sysv/linux/i386/pthread_barrier_wait.S
|
||||
+++ /dev/null
|
||||
@@ -1,187 +0,0 @@
|
||||
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
|
||||
- This file is part of the GNU C Library.
|
||||
- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
-
|
||||
- The GNU C Library is free software; you can redistribute it and/or
|
||||
- modify it under the terms of the GNU Lesser General Public
|
||||
- License as published by the Free Software Foundation; either
|
||||
- version 2.1 of the License, or (at your option) any later version.
|
||||
-
|
||||
- The GNU C Library is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- Lesser General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Lesser General Public
|
||||
- License along with the GNU C Library; if not, see
|
||||
- <http://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-#include <sysdep.h>
|
||||
-#include <lowlevellock.h>
|
||||
-#include <lowlevelbarrier.h>
|
||||
-
|
||||
- .text
|
||||
-
|
||||
- .globl __pthread_barrier_wait
|
||||
- .type __pthread_barrier_wait,@function
|
||||
- .align 16
|
||||
-__pthread_barrier_wait:
|
||||
- cfi_startproc
|
||||
- pushl %ebx
|
||||
- cfi_adjust_cfa_offset(4)
|
||||
- cfi_offset(%ebx, -8)
|
||||
-
|
||||
- movl 8(%esp), %ebx
|
||||
-
|
||||
- /* Get the mutex. */
|
||||
- movl $1, %edx
|
||||
- xorl %eax, %eax
|
||||
- LOCK
|
||||
- cmpxchgl %edx, MUTEX(%ebx)
|
||||
- jnz 1f
|
||||
-
|
||||
- /* One less waiter. If this was the last one needed wake
|
||||
- everybody. */
|
||||
-2: subl $1, LEFT(%ebx)
|
||||
- je 3f
|
||||
-
|
||||
- /* There are more threads to come. */
|
||||
- pushl %esi
|
||||
- cfi_adjust_cfa_offset(4)
|
||||
- cfi_offset(%esi, -12)
|
||||
-
|
||||
-#if CURR_EVENT == 0
|
||||
- movl (%ebx), %edx
|
||||
-#else
|
||||
- movl CURR_EVENT(%ebx), %edx
|
||||
-#endif
|
||||
-
|
||||
- /* Release the mutex. */
|
||||
- LOCK
|
||||
- subl $1, MUTEX(%ebx)
|
||||
- jne 6f
|
||||
-
|
||||
- /* Wait for the remaining threads. The call will return immediately
|
||||
- if the CURR_EVENT memory has meanwhile been changed. */
|
||||
-7:
|
||||
-#if FUTEX_WAIT == 0
|
||||
- movl PRIVATE(%ebx), %ecx
|
||||
-#else
|
||||
- movl $FUTEX_WAIT, %ecx
|
||||
- orl PRIVATE(%ebx), %ecx
|
||||
-#endif
|
||||
- xorl %esi, %esi
|
||||
-8: movl $SYS_futex, %eax
|
||||
- ENTER_KERNEL
|
||||
-
|
||||
- /* Don't return on spurious wakeups. The syscall does not change
|
||||
- any register except %eax so there is no need to reload any of
|
||||
- them. */
|
||||
-#if CURR_EVENT == 0
|
||||
- cmpl %edx, (%ebx)
|
||||
-#else
|
||||
- cmpl %edx, CURR_EVENT(%ebx)
|
||||
-#endif
|
||||
- je 8b
|
||||
-
|
||||
- /* Increment LEFT. If this brings the count back to the
|
||||
- initial count unlock the object. */
|
||||
- movl $1, %edx
|
||||
- movl INIT_COUNT(%ebx), %ecx
|
||||
- LOCK
|
||||
- xaddl %edx, LEFT(%ebx)
|
||||
- subl $1, %ecx
|
||||
- cmpl %ecx, %edx
|
||||
- jne 10f
|
||||
-
|
||||
- /* Release the mutex. We cannot release the lock before
|
||||
- waking the waiting threads since otherwise a new thread might
|
||||
- arrive and gets waken up, too. */
|
||||
- LOCK
|
||||
- subl $1, MUTEX(%ebx)
|
||||
- jne 9f
|
||||
-
|
||||
- /* Note: %esi is still zero. */
|
||||
-10: movl %esi, %eax /* != PTHREAD_BARRIER_SERIAL_THREAD */
|
||||
-
|
||||
- popl %esi
|
||||
- cfi_adjust_cfa_offset(-4)
|
||||
- cfi_restore(%esi)
|
||||
- popl %ebx
|
||||
- cfi_adjust_cfa_offset(-4)
|
||||
- cfi_restore(%ebx)
|
||||
- ret
|
||||
-
|
||||
- cfi_adjust_cfa_offset(4)
|
||||
- cfi_offset(%ebx, -8)
|
||||
-
|
||||
- /* The necessary number of threads arrived. */
|
||||
-3:
|
||||
-#if CURR_EVENT == 0
|
||||
- addl $1, (%ebx)
|
||||
-#else
|
||||
- addl $1, CURR_EVENT(%ebx)
|
||||
-#endif
|
||||
-
|
||||
- /* Wake up all waiters. The count is a signed number in the kernel
|
||||
- so 0x7fffffff is the highest value. */
|
||||
- movl $0x7fffffff, %edx
|
||||
- movl $FUTEX_WAKE, %ecx
|
||||
- orl PRIVATE(%ebx), %ecx
|
||||
- movl $SYS_futex, %eax
|
||||
- ENTER_KERNEL
|
||||
-
|
||||
- /* Increment LEFT. If this brings the count back to the
|
||||
- initial count unlock the object. */
|
||||
- movl $1, %edx
|
||||
- movl INIT_COUNT(%ebx), %ecx
|
||||
- LOCK
|
||||
- xaddl %edx, LEFT(%ebx)
|
||||
- subl $1, %ecx
|
||||
- cmpl %ecx, %edx
|
||||
- jne 5f
|
||||
-
|
||||
- /* Release the mutex. We cannot release the lock before
|
||||
- waking the waiting threads since otherwise a new thread might
|
||||
- arrive and gets waken up, too. */
|
||||
- LOCK
|
||||
- subl $1, MUTEX(%ebx)
|
||||
- jne 4f
|
||||
-
|
||||
-5: orl $-1, %eax /* == PTHREAD_BARRIER_SERIAL_THREAD */
|
||||
-
|
||||
- popl %ebx
|
||||
- cfi_adjust_cfa_offset(-4)
|
||||
- cfi_restore(%ebx)
|
||||
- ret
|
||||
-
|
||||
- cfi_adjust_cfa_offset(4)
|
||||
- cfi_offset(%ebx, -8)
|
||||
-1: movl PRIVATE(%ebx), %ecx
|
||||
- leal MUTEX(%ebx), %edx
|
||||
- xorl $LLL_SHARED, %ecx
|
||||
- call __lll_lock_wait
|
||||
- jmp 2b
|
||||
-
|
||||
-4: movl PRIVATE(%ebx), %ecx
|
||||
- leal MUTEX(%ebx), %eax
|
||||
- xorl $LLL_SHARED, %ecx
|
||||
- call __lll_unlock_wake
|
||||
- jmp 5b
|
||||
-
|
||||
- cfi_adjust_cfa_offset(4)
|
||||
- cfi_offset(%esi, -12)
|
||||
-6: movl PRIVATE(%ebx), %ecx
|
||||
- leal MUTEX(%ebx), %eax
|
||||
- xorl $LLL_SHARED, %ecx
|
||||
- call __lll_unlock_wake
|
||||
- jmp 7b
|
||||
-
|
||||
-9: movl PRIVATE(%ebx), %ecx
|
||||
- leal MUTEX(%ebx), %eax
|
||||
- xorl $LLL_SHARED, %ecx
|
||||
- call __lll_unlock_wake
|
||||
- jmp 10b
|
||||
- cfi_endproc
|
||||
- .size __pthread_barrier_wait,.-__pthread_barrier_wait
|
||||
-weak_alias (__pthread_barrier_wait, pthread_barrier_wait)
|
||||
Index: glibc-2.22-621-g90c400b/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S
|
||||
===================================================================
|
||||
--- glibc-2.22-621-g90c400b.orig/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S
|
||||
+++ /dev/null
|
||||
@@ -1,161 +0,0 @@
|
||||
-/* Copyright (C) 2002-2015 Free Software Foundation, Inc.
|
||||
- This file is part of the GNU C Library.
|
||||
- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
-
|
||||
- The GNU C Library is free software; you can redistribute it and/or
|
||||
- modify it under the terms of the GNU Lesser General Public
|
||||
- License as published by the Free Software Foundation; either
|
||||
- version 2.1 of the License, or (at your option) any later version.
|
||||
-
|
||||
- The GNU C Library is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
- Lesser General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Lesser General Public
|
||||
- License along with the GNU C Library; if not, see
|
||||
- <http://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-#include <sysdep.h>
|
||||
-#include <lowlevellock.h>
|
||||
-#include <lowlevelbarrier.h>
|
||||
-
|
||||
-
|
||||
- .text
|
||||
-
|
||||
- .globl __pthread_barrier_wait
|
||||
- .type __pthread_barrier_wait,@function
|
||||
- .align 16
|
||||
-__pthread_barrier_wait:
|
||||
- /* Get the mutex. */
|
||||
- xorl %eax, %eax
|
||||
- movl $1, %esi
|
||||
- LOCK
|
||||
- cmpxchgl %esi, MUTEX(%rdi)
|
||||
- jnz 1f
|
||||
-
|
||||
- /* One less waiter. If this was the last one needed wake
|
||||
- everybody. */
|
||||
-2: decl LEFT(%rdi)
|
||||
- je 3f
|
||||
-
|
||||
- /* There are more threads to come. */
|
||||
-#if CURR_EVENT == 0
|
||||
- movl (%rdi), %edx
|
||||
-#else
|
||||
- movl CURR_EVENT(%rdi), %edx
|
||||
-#endif
|
||||
-
|
||||
- /* Release the mutex. */
|
||||
- LOCK
|
||||
- decl MUTEX(%rdi)
|
||||
- jne 6f
|
||||
-
|
||||
- /* Wait for the remaining threads. The call will return immediately
|
||||
- if the CURR_EVENT memory has meanwhile been changed. */
|
||||
-7:
|
||||
-#if FUTEX_WAIT == 0
|
||||
- movl PRIVATE(%rdi), %esi
|
||||
-#else
|
||||
- movl $FUTEX_WAIT, %esi
|
||||
- orl PRIVATE(%rdi), %esi
|
||||
-#endif
|
||||
- xorq %r10, %r10
|
||||
-8: movl $SYS_futex, %eax
|
||||
- syscall
|
||||
-
|
||||
- /* Don't return on spurious wakeups. The syscall does not change
|
||||
- any register except %eax so there is no need to reload any of
|
||||
- them. */
|
||||
-#if CURR_EVENT == 0
|
||||
- cmpl %edx, (%rdi)
|
||||
-#else
|
||||
- cmpl %edx, CURR_EVENT(%rdi)
|
||||
-#endif
|
||||
- je 8b
|
||||
-
|
||||
- /* Increment LEFT. If this brings the count back to the
|
||||
- initial count unlock the object. */
|
||||
- movl $1, %edx
|
||||
- movl INIT_COUNT(%rdi), %eax
|
||||
- LOCK
|
||||
- xaddl %edx, LEFT(%rdi)
|
||||
- subl $1, %eax
|
||||
- cmpl %eax, %edx
|
||||
- jne,pt 10f
|
||||
-
|
||||
- /* Release the mutex. We cannot release the lock before
|
||||
- waking the waiting threads since otherwise a new thread might
|
||||
- arrive and gets waken up, too. */
|
||||
- LOCK
|
||||
- decl MUTEX(%rdi)
|
||||
- jne 9f
|
||||
-
|
||||
-10: xorl %eax, %eax /* != PTHREAD_BARRIER_SERIAL_THREAD */
|
||||
-
|
||||
- retq
|
||||
-
|
||||
- /* The necessary number of threads arrived. */
|
||||
-3:
|
||||
-#if CURR_EVENT == 0
|
||||
- incl (%rdi)
|
||||
-#else
|
||||
- incl CURR_EVENT(%rdi)
|
||||
-#endif
|
||||
-
|
||||
- /* Wake up all waiters. The count is a signed number in the kernel
|
||||
- so 0x7fffffff is the highest value. */
|
||||
- movl $0x7fffffff, %edx
|
||||
- movl $FUTEX_WAKE, %esi
|
||||
- orl PRIVATE(%rdi), %esi
|
||||
- movl $SYS_futex, %eax
|
||||
- syscall
|
||||
-
|
||||
- /* Increment LEFT. If this brings the count back to the
|
||||
- initial count unlock the object. */
|
||||
- movl $1, %edx
|
||||
- movl INIT_COUNT(%rdi), %eax
|
||||
- LOCK
|
||||
- xaddl %edx, LEFT(%rdi)
|
||||
- subl $1, %eax
|
||||
- cmpl %eax, %edx
|
||||
- jne,pt 5f
|
||||
-
|
||||
- /* Release the mutex. We cannot release the lock before
|
||||
- waking the waiting threads since otherwise a new thread might
|
||||
- arrive and gets waken up, too. */
|
||||
- LOCK
|
||||
- decl MUTEX(%rdi)
|
||||
- jne 4f
|
||||
-
|
||||
-5: orl $-1, %eax /* == PTHREAD_BARRIER_SERIAL_THREAD */
|
||||
-
|
||||
- retq
|
||||
-
|
||||
-1: movl PRIVATE(%rdi), %esi
|
||||
- addq $MUTEX, %rdi
|
||||
- xorl $LLL_SHARED, %esi
|
||||
- callq __lll_lock_wait
|
||||
- subq $MUTEX, %rdi
|
||||
- jmp 2b
|
||||
-
|
||||
-4: movl PRIVATE(%rdi), %esi
|
||||
- addq $MUTEX, %rdi
|
||||
- xorl $LLL_SHARED, %esi
|
||||
- callq __lll_unlock_wake
|
||||
- jmp 5b
|
||||
-
|
||||
-6: movl PRIVATE(%rdi), %esi
|
||||
- addq $MUTEX, %rdi
|
||||
- xorl $LLL_SHARED, %esi
|
||||
- callq __lll_unlock_wake
|
||||
- subq $MUTEX, %rdi
|
||||
- jmp 7b
|
||||
-
|
||||
-9: movl PRIVATE(%rdi), %esi
|
||||
- addq $MUTEX, %rdi
|
||||
- xorl $LLL_SHARED, %esi
|
||||
- callq __lll_unlock_wake
|
||||
- jmp 10b
|
||||
- .size __pthread_barrier_wait,.-__pthread_barrier_wait
|
||||
-weak_alias (__pthread_barrier_wait, pthread_barrier_wait)
|
@ -1,40 +0,0 @@
|
||||
Use python3 for installed executable python scripts.
|
||||
|
||||
Fedora is a Python3-only distribution:
|
||||
https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3
|
||||
|
||||
This fixes build failures where builders may strictly enforce only
|
||||
python3 during a transitional phase.
|
||||
|
||||
Author: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/benchtests/scripts/compare_bench.py b/benchtests/scripts/compare_bench.py
|
||||
index c1c438a1c9f0eae6..b7d3d7bcee87969d 100755
|
||||
--- a/benchtests/scripts/compare_bench.py
|
||||
+++ b/benchtests/scripts/compare_bench.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
# Copyright (C) 2015-2019 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
#
|
||||
diff --git a/benchtests/scripts/import_bench.py b/benchtests/scripts/import_bench.py
|
||||
index 7a55d19f038e64d4..72e6034243a8c9b6 100644
|
||||
--- a/benchtests/scripts/import_bench.py
|
||||
+++ b/benchtests/scripts/import_bench.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
# Copyright (C) 2015-2019 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
#
|
||||
diff --git a/benchtests/scripts/validate_benchout.py b/benchtests/scripts/validate_benchout.py
|
||||
index 55d07c6bce5b5184..04129f9c26c2874c 100755
|
||||
--- a/benchtests/scripts/validate_benchout.py
|
||||
+++ b/benchtests/scripts/validate_benchout.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
# Copyright (C) 2014-2019 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
#
|
29
glibc-res-hconf-gcc5.patch
Normal file
29
glibc-res-hconf-gcc5.patch
Normal file
@ -0,0 +1,29 @@
|
||||
Index: glibc-2.22-386-g95e8397/resolv/res_hconf.c
|
||||
===================================================================
|
||||
--- glibc-2.22-386-g95e8397.orig/resolv/res_hconf.c
|
||||
+++ glibc-2.22-386-g95e8397/resolv/res_hconf.c
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "res_hconf.h"
|
||||
#include <wchar.h>
|
||||
#include <atomic.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
#if IS_IN (libc)
|
||||
# define fgets_unlocked __fgets_unlocked
|
||||
@@ -577,7 +578,16 @@ _res_hconf_trim_domain (char *hostname)
|
||||
|
||||
for (i = 0; i < _res_hconf.num_trimdomains; ++i)
|
||||
{
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since i is limited to
|
||||
+ num_trimdomains which is limited to <= TRIMDOMAINS_MAX. This
|
||||
+ is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
const char *trim = _res_hconf.trimdomain[i];
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
trim_len = strlen (trim);
|
||||
if (hostname_len > trim_len
|
19
glibc-rh1009145.patch
Normal file
19
glibc-rh1009145.patch
Normal file
@ -0,0 +1,19 @@
|
||||
--- glibc-2.18-151-g303e567.orig/elf/ldconfig.c 2013-09-25 14:01:01.522446341 -0400
|
||||
+++ glibc-2.18-151-g303e567/elf/ldconfig.c 2013-09-25 14:06:31.094218857 -0400
|
||||
@@ -959,6 +959,16 @@
|
||||
|| dlib_ptr->flag == FLAG_ELF_LIBC6)
|
||||
&& flag == FLAG_ELF)
|
||||
dlib_ptr->flag = flag;
|
||||
+#ifdef __arm__
|
||||
+ /* In Fedora 20 binutils regressed temporarily and failed to
|
||||
+ mark hard ABI objects with the correct flag. Therefore we
|
||||
+ must accept unmarked objects that were previously marked
|
||||
+ hard ABI. We can remove this check once the entire distribution
|
||||
+ has been rebuilt. */
|
||||
+ else if (dlib_ptr->flag & FLAG_ARM_LIBHF &&
|
||||
+ (flag == FLAG_ELF_LIBC6))
|
||||
+ ;
|
||||
+#endif
|
||||
else
|
||||
error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
|
||||
dlib_ptr->name, direntry->d_name,
|
90
glibc-rh1013801.patch
Normal file
90
glibc-rh1013801.patch
Normal file
@ -0,0 +1,90 @@
|
||||
#
|
||||
# Posted upstream:
|
||||
# https://sourceware.org/ml/libc-alpha/2013-10/msg00065.html
|
||||
#
|
||||
# This is related to bug 1013801 in that it fixes the problem
|
||||
# by modifying the runtime. In bug 1013801 we have libselinux
|
||||
# using pthread_atfork which pulls in libpthread, but we don't
|
||||
# want that, we want libpthread to be pulled in only when
|
||||
# actually needed by the application. This patch makes it
|
||||
# possible to avoid requiring libpthread and still use
|
||||
# pthread_atfork.
|
||||
#
|
||||
# The general idea for the design is in the leading comment
|
||||
# in the source code.
|
||||
#
|
||||
diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile
|
||||
index 6078e2d..36fd50b 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \
|
||||
libc-cleanup libc_pthread_init libc_multiple_threads \
|
||||
- register-atfork unregister-atfork
|
||||
+ register-atfork unregister-atfork libc_pthread_atfork
|
||||
+
|
||||
+static-only-routines += libc_pthread_atfork
|
||||
shared-only-routines = forward
|
||||
|
||||
libpthread-routines = nptl-init vars events version pt-interp \
|
||||
diff --git a/nptl/libc_pthread_atfork.c b/nptl/libc_pthread_atfork.c
|
||||
new file mode 100644
|
||||
index 0000000..667049a
|
||||
--- /dev/null
|
||||
+++ b/nptl/libc_pthread_atfork.c
|
||||
@@ -0,0 +1,54 @@
|
||||
+/* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* The standard design pattern for making it optional to link against
|
||||
+ libpthread is to mark the function weak, test if the function
|
||||
+ address is non-zero and call the function, otherwise use a fallback.
|
||||
+ The problem with pthread_atfork is that there is no viable
|
||||
+ fallback. If you need to do something during fork it has to be done
|
||||
+ via pthread_atfork. This makes having libpthread optional and using
|
||||
+ pthread_atfork impossible. We make it possible by providing
|
||||
+ pthread_atfork in libc_nonshared.a. The real work of pthread_atfork
|
||||
+ is done by __register_atfork which is already provided in
|
||||
+ libc_nonshared.a. It's included in libc_nonshared.a because
|
||||
+ __dso_handle has to be unique to each DSO such that unloading the DSO
|
||||
+ can unregister the atfork handlers. We build pthread_atfork again
|
||||
+ under a different file name and include it into libc_nonshared.a and
|
||||
+ libc.a. We keep pthread_atfork in libpthread_nonshared.a and
|
||||
+ libpthread.a for compatibility and completeness.
|
||||
+
|
||||
+ Applications that can't rely on a new glibc should use the following
|
||||
+ code to optionally include libpthread and still register a function
|
||||
+ via pthread_atfork i.e. use __register_atfork directly:
|
||||
+
|
||||
+ extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
|
||||
+ extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
|
||||
+
|
||||
+ static int __app_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
|
||||
+ {
|
||||
+ return __register_atfork (prepare, parent, child,
|
||||
+ &__dso_handle == NULL ? NULL : __dso_handle);
|
||||
+ }
|
||||
+
|
||||
+ This code requires glibc 2.3.2 or newer. Previous to 2.3.2 no such
|
||||
+ interfaces exist and at that point is is impossible to have an
|
||||
+ optional libpthread and call pthread_atfork.
|
||||
+
|
||||
+ This code adds no more ABI requirements than already exist since
|
||||
+ __dso_handle and __register_atfork are already part of the ABI. */
|
||||
+#include <pthread_atfork.c>
|
47
glibc-rh1052846.patch
Normal file
47
glibc-rh1052846.patch
Normal file
@ -0,0 +1,47 @@
|
||||
commit 403ce35141da511898cde550f48ebc68a2a3ac82
|
||||
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Date: Mon Jan 6 14:37:21 2014 +0530
|
||||
|
||||
Fix infinite loop in ftell when writing wide char data (BZ #16398)
|
||||
|
||||
ftell tries to avoid flushing the buffer when it is in write mode by
|
||||
converting the wide char data and placing it into the binary buffer.
|
||||
If the output buffer space is full and there is data to write, the
|
||||
code reverts to flushing the buffer. This breaks when there is space
|
||||
in the buffer but it is not enough to convert the next character in
|
||||
the wide data buffer, due to which __codecvt_do_out returns a
|
||||
__codecvt_partial status. In this case, ftell keeps running in an
|
||||
infinite loop.
|
||||
|
||||
The fix here is to detect the __codecvt_partial status in addition to
|
||||
checking if the buffer is full.
|
||||
|
||||
diff --git a/libio/wfileops.c b/libio/wfileops.c
|
||||
index 87d3cdc..877fc1f 100644
|
||||
--- a/libio/wfileops.c
|
||||
+++ b/libio/wfileops.c
|
||||
@@ -715,7 +715,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
- fp->_wide_data->_IO_write_base) / clen;
|
||||
else
|
||||
{
|
||||
- enum __codecvt_result status;
|
||||
+ enum __codecvt_result status = __codecvt_ok;
|
||||
delta = (fp->_wide_data->_IO_write_ptr
|
||||
- fp->_wide_data->_IO_write_base);
|
||||
const wchar_t *write_base = fp->_wide_data->_IO_write_base;
|
||||
@@ -728,9 +728,12 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
flush buffers for every ftell. */
|
||||
do
|
||||
{
|
||||
- /* Ugh, no point trying to avoid the flush. Just do it
|
||||
- and go back to how it was with the read mode. */
|
||||
- if (delta > 0 && new_write_ptr == fp->_IO_buf_end)
|
||||
+ /* There is not enough space in the buffer to do the entire
|
||||
+ conversion, so there is no point trying to avoid the
|
||||
+ buffer flush. Just do it and go back to how it was with
|
||||
+ the read mode. */
|
||||
+ if (status == __codecvt_partial
|
||||
+ || (delta > 0 && new_write_ptr == fp->_IO_buf_end))
|
||||
{
|
||||
if (_IO_switch_to_wget_mode (fp))
|
||||
return WEOF;
|
836
glibc-rh1069559-1.patch
Normal file
836
glibc-rh1069559-1.patch
Normal file
@ -0,0 +1,836 @@
|
||||
commit 03425ba6ab17b87b2c64f0d7b47fb0b86add9993
|
||||
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Date: Thu Feb 20 15:41:18 2014 +0530
|
||||
|
||||
Separate ftell from fseek logic and avoid modifying FILE data (#16532)
|
||||
|
||||
ftell semantics are distinct from fseek(SEEK_CUR) especially when it
|
||||
is called on a file handler that is not yet active. Due to this
|
||||
caveat, much care needs to be taken while modifying the handler data
|
||||
and hence, this first iteration on separating out ftell focusses on
|
||||
maintaining handler data integrity at all times while it figures out
|
||||
the current stream offset. The result is that it makes a syscall for
|
||||
every offset request.
|
||||
|
||||
There is scope for optimizing this by caching offsets when we know
|
||||
that the handler is active. A simple way to find out is when the
|
||||
buffers have data. It is not so simple to find this out when the
|
||||
buffer is empty without adding some kind of flag.
|
||||
|
||||
diff --git a/libio/Makefile b/libio/Makefile
|
||||
index 8c333ce..8ccd80f 100644
|
||||
--- a/libio/Makefile
|
||||
+++ b/libio/Makefile
|
||||
@@ -60,7 +60,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
|
||||
tst-wmemstream1 tst-wmemstream2 \
|
||||
bug-memstream1 bug-wmemstream1 \
|
||||
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
|
||||
- tst-fwrite-error tst-ftell-partial-wide
|
||||
+ tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler
|
||||
ifeq (yes,$(build-shared))
|
||||
# Add test-fopenloc only if shared library is enabled since it depends on
|
||||
# shared localedata objects.
|
||||
diff --git a/libio/fileops.c b/libio/fileops.c
|
||||
index a3499be..a177302 100644
|
||||
--- a/libio/fileops.c
|
||||
+++ b/libio/fileops.c
|
||||
@@ -931,6 +931,59 @@ _IO_file_sync_mmap (_IO_FILE *fp)
|
||||
|
||||
|
||||
_IO_off64_t
|
||||
+get_file_offset (_IO_FILE *fp)
|
||||
+{
|
||||
+ if ((fp->_flags & _IO_IS_APPENDING) == _IO_IS_APPENDING)
|
||||
+ {
|
||||
+ struct stat64 st;
|
||||
+ bool ret = (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode));
|
||||
+ if (ret)
|
||||
+ return st.st_size;
|
||||
+ else
|
||||
+ return EOF;
|
||||
+ }
|
||||
+ else
|
||||
+ return _IO_SYSSEEK (fp, 0, _IO_seek_cur);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* ftell{,o} implementation. Don't modify any state of the file pointer while
|
||||
+ we try to get the current state of the stream. */
|
||||
+static _IO_off64_t
|
||||
+do_ftell (_IO_FILE *fp)
|
||||
+{
|
||||
+ _IO_off64_t result;
|
||||
+
|
||||
+ result = get_file_offset (fp);
|
||||
+
|
||||
+ if (result == EOF)
|
||||
+ return result;
|
||||
+
|
||||
+ /* No point looking at unflushed data if we haven't allocated buffers
|
||||
+ yet. */
|
||||
+ if (fp->_IO_buf_base != NULL)
|
||||
+ {
|
||||
+ bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
|
||||
+ || _IO_in_put_mode (fp));
|
||||
+
|
||||
+ /* Adjust for unflushed data. */
|
||||
+ if (!was_writing)
|
||||
+ result -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
+ else
|
||||
+ result += fp->_IO_write_ptr - fp->_IO_read_end;
|
||||
+ }
|
||||
+
|
||||
+ if (result < 0)
|
||||
+ {
|
||||
+ __set_errno (EINVAL);
|
||||
+ return EOF;
|
||||
+ }
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+_IO_off64_t
|
||||
_IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
_IO_FILE *fp;
|
||||
_IO_off64_t offset;
|
||||
@@ -940,6 +993,13 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
_IO_off64_t result;
|
||||
_IO_off64_t delta, new_offset;
|
||||
long count;
|
||||
+
|
||||
+ /* Short-circuit into a separate function. We don't want to mix any
|
||||
+ functionality and we don't want to touch anything inside the FILE
|
||||
+ object. */
|
||||
+ if (mode == 0)
|
||||
+ return do_ftell (fp);
|
||||
+
|
||||
/* POSIX.1 8.2.3.7 says that after a call the fflush() the file
|
||||
offset of the underlying file must be exact. */
|
||||
int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
|
||||
@@ -948,9 +1008,6 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
|
||||
|| _IO_in_put_mode (fp));
|
||||
|
||||
- if (mode == 0)
|
||||
- dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
|
||||
-
|
||||
/* Flush unwritten characters.
|
||||
(This may do an unneeded write if we seek within the buffer.
|
||||
But to be able to switch to reading, we would need to set
|
||||
@@ -958,7 +1015,7 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
which assumes file_ptr() is eGptr. Anyway, since we probably
|
||||
end up flushing when we close(), it doesn't make much difference.)
|
||||
FIXME: simulate mem-mapped files. */
|
||||
- else if (was_writing && _IO_switch_to_get_mode (fp))
|
||||
+ if (was_writing && _IO_switch_to_get_mode (fp))
|
||||
return EOF;
|
||||
|
||||
if (fp->_IO_buf_base == NULL)
|
||||
@@ -978,30 +1035,10 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
{
|
||||
case _IO_seek_cur:
|
||||
/* Adjust for read-ahead (bytes is buffer). */
|
||||
- if (mode != 0 || !was_writing)
|
||||
- offset -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
- else
|
||||
- {
|
||||
- /* _IO_read_end coincides with fp._offset, so the actual file position
|
||||
- is fp._offset - (_IO_read_end - new_write_ptr). This is fine
|
||||
- even if fp._offset is not set, since fp->_IO_read_end is then at
|
||||
- _IO_buf_base and this adjustment is for unbuffered output. */
|
||||
- offset -= fp->_IO_read_end - fp->_IO_write_ptr;
|
||||
- }
|
||||
+ offset -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
|
||||
if (fp->_offset == _IO_pos_BAD)
|
||||
- {
|
||||
- if (mode != 0)
|
||||
- goto dumb;
|
||||
- else
|
||||
- {
|
||||
- result = _IO_SYSSEEK (fp, 0, dir);
|
||||
- if (result == EOF)
|
||||
- return result;
|
||||
-
|
||||
- fp->_offset = result;
|
||||
- }
|
||||
- }
|
||||
+ goto dumb;
|
||||
/* Make offset absolute, assuming current pointer is file_ptr(). */
|
||||
offset += fp->_offset;
|
||||
if (offset < 0)
|
||||
@@ -1028,10 +1065,6 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
}
|
||||
/* At this point, dir==_IO_seek_set. */
|
||||
|
||||
- /* If we are only interested in the current position we've found it now. */
|
||||
- if (mode == 0)
|
||||
- return offset;
|
||||
-
|
||||
/* If destination is within current buffer, optimize: */
|
||||
if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
|
||||
&& !_IO_in_backup (fp))
|
||||
diff --git a/libio/libioP.h b/libio/libioP.h
|
||||
index 4ca723c..8a7b85b 100644
|
||||
--- a/libio/libioP.h
|
||||
+++ b/libio/libioP.h
|
||||
@@ -397,6 +397,7 @@ extern void _IO_wdoallocbuf (_IO_FILE *) __THROW;
|
||||
libc_hidden_proto (_IO_wdoallocbuf)
|
||||
extern void _IO_unsave_wmarkers (_IO_FILE *) __THROW;
|
||||
extern unsigned _IO_adjust_wcolumn (unsigned, const wchar_t *, int) __THROW;
|
||||
+extern _IO_off64_t get_file_offset (_IO_FILE *fp);
|
||||
|
||||
/* Marker-related function. */
|
||||
|
||||
diff --git a/libio/tst-ftell-active-handler.c b/libio/tst-ftell-active-handler.c
|
||||
new file mode 100644
|
||||
index 0000000..aac2923
|
||||
--- /dev/null
|
||||
+++ b/libio/tst-ftell-active-handler.c
|
||||
@@ -0,0 +1,366 @@
|
||||
+/* Verify that ftell returns the correct value at various points before and
|
||||
+ after the handler on which it is called becomes active.
|
||||
+ Copyright (C) 2014 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <errno.h>
|
||||
+#include <unistd.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <locale.h>
|
||||
+#include <wchar.h>
|
||||
+
|
||||
+static int do_test (void);
|
||||
+
|
||||
+#define TEST_FUNCTION do_test ()
|
||||
+#include "../test-skeleton.c"
|
||||
+
|
||||
+#define get_handles_fdopen(filename, fd, fp, fd_mode, mode) \
|
||||
+({ \
|
||||
+ int ret = 0; \
|
||||
+ (fd) = open ((filename), (fd_mode), 0); \
|
||||
+ if ((fd) == -1) \
|
||||
+ { \
|
||||
+ printf ("open failed: %m\n"); \
|
||||
+ ret = 1; \
|
||||
+ } \
|
||||
+ else \
|
||||
+ { \
|
||||
+ (fp) = fdopen ((fd), (mode)); \
|
||||
+ if ((fp) == NULL) \
|
||||
+ { \
|
||||
+ printf ("fdopen failed: %m\n"); \
|
||||
+ close (fd); \
|
||||
+ ret = 1; \
|
||||
+ } \
|
||||
+ } \
|
||||
+ ret; \
|
||||
+})
|
||||
+
|
||||
+#define get_handles_fopen(filename, fd, fp, mode) \
|
||||
+({ \
|
||||
+ int ret = 0; \
|
||||
+ (fp) = fopen ((filename), (mode)); \
|
||||
+ if ((fp) == NULL) \
|
||||
+ { \
|
||||
+ printf ("fopen failed: %m\n"); \
|
||||
+ ret = 1; \
|
||||
+ } \
|
||||
+ else \
|
||||
+ { \
|
||||
+ (fd) = fileno (fp); \
|
||||
+ if ((fd) == -1) \
|
||||
+ { \
|
||||
+ printf ("fileno failed: %m\n"); \
|
||||
+ ret = 1; \
|
||||
+ } \
|
||||
+ } \
|
||||
+ ret; \
|
||||
+})
|
||||
+
|
||||
+static const void *data;
|
||||
+static const char *char_data = "abcdef";
|
||||
+static const wchar_t *wide_data = L"abcdef";
|
||||
+static size_t data_len;
|
||||
+/* Maintain the current file length for validation. */
|
||||
+static size_t file_len;
|
||||
+
|
||||
+typedef int (*fputs_func_t) (const void *data, FILE *fp);
|
||||
+fputs_func_t fputs_func;
|
||||
+
|
||||
+/* Test that the value of ftell is not cached when the stream handle is not
|
||||
+ active. */
|
||||
+static int
|
||||
+do_ftell_test (const char *filename)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ struct test
|
||||
+ {
|
||||
+ const char *mode;
|
||||
+ int fd_mode;
|
||||
+ size_t old_off;
|
||||
+ size_t new_off;
|
||||
+ } test_modes[] = {
|
||||
+ {"w", O_WRONLY, 0, data_len},
|
||||
+ {"w+", O_RDWR, 0, data_len},
|
||||
+ {"r+", O_RDWR, 0, data_len},
|
||||
+ {"a", O_WRONLY, data_len, 2 * data_len},
|
||||
+ {"a+", O_RDWR, 2 * data_len, 3 * data_len},
|
||||
+ };
|
||||
+ for (int j = 0; j < 2; j++)
|
||||
+ {
|
||||
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
|
||||
+ {
|
||||
+ FILE *fp;
|
||||
+ int fd;
|
||||
+ printf ("\tftell: %s (file, \"%s\"): ", j == 0 ? "fdopen" : "fopen",
|
||||
+ test_modes[i].mode);
|
||||
+
|
||||
+ if (j == 0)
|
||||
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
|
||||
+ test_modes[i].mode);
|
||||
+ else
|
||||
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
|
||||
+
|
||||
+ if (ret != 0)
|
||||
+ return 1;
|
||||
+
|
||||
+ long off = ftell (fp);
|
||||
+ if (off != test_modes[i].old_off)
|
||||
+ {
|
||||
+ printf ("Incorrect old offset. Expected %zu but got %ld, ",
|
||||
+ test_modes[i].old_off, off);
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+ else
|
||||
+ printf ("old offset = %ld, ", off);
|
||||
+
|
||||
+ int ret = write (fd, data, data_len);
|
||||
+ off = ftell (fp);
|
||||
+
|
||||
+ if (off != test_modes[i].new_off)
|
||||
+ {
|
||||
+ printf ("Incorrect new offset. Expected %zu but got %ld\n",
|
||||
+ test_modes[i].old_off, off);
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+ else
|
||||
+ printf ("new offset = %ld\n", off);
|
||||
+
|
||||
+ fclose (fp);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* This test opens the file for writing, moves the file offset of the
|
||||
+ underlying file, writes out data and then checks if ftell trips on it. */
|
||||
+static int
|
||||
+do_write_test (const char *filename)
|
||||
+{
|
||||
+ FILE *fp = NULL;
|
||||
+ int fd;
|
||||
+ int ret = 0;
|
||||
+ struct test
|
||||
+ {
|
||||
+ const char *mode;
|
||||
+ int fd_mode;
|
||||
+ } test_modes[] = {
|
||||
+ {"w", O_WRONLY},
|
||||
+ {"w+", O_RDWR},
|
||||
+ {"r+", O_RDWR}
|
||||
+ };
|
||||
+
|
||||
+ for (int j = 0; j < 2; j++)
|
||||
+ {
|
||||
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
|
||||
+ {
|
||||
+ printf ("\twrite: %s (file, \"%s\"): ", j == 0 ? "fopen" : "fdopen",
|
||||
+ test_modes[i].mode);
|
||||
+
|
||||
+ if (j == 0)
|
||||
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
|
||||
+ else
|
||||
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
|
||||
+ test_modes[i].mode);
|
||||
+
|
||||
+ if (ret != 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Move offset to just before the end of the file. */
|
||||
+ off_t ret = lseek (fd, file_len - 1, SEEK_SET);
|
||||
+ if (ret == -1)
|
||||
+ {
|
||||
+ printf ("lseek failed: %m\n");
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Write some data. */
|
||||
+ size_t written = fputs_func (data, fp);
|
||||
+
|
||||
+ if (written == EOF)
|
||||
+ {
|
||||
+ printf ("fputs[1] failed to write data\n");
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Verify that the offset points to the end of the file. */
|
||||
+ long offset = ftell (fp);
|
||||
+ file_len = file_len - 1 + data_len;
|
||||
+
|
||||
+ if (offset != file_len)
|
||||
+ {
|
||||
+ printf ("Incorrect offset. Expected %zu, but got %ld\n",
|
||||
+ file_len, offset);
|
||||
+
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+
|
||||
+ printf ("offset = %ld\n", offset);
|
||||
+ fclose (fp);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* This test opens a file in append mode, writes some data, and then verifies
|
||||
+ that ftell does not trip over it. */
|
||||
+static int
|
||||
+do_append_test (const char *filename)
|
||||
+{
|
||||
+ FILE *fp = NULL;
|
||||
+ int ret = 0;
|
||||
+ int fd;
|
||||
+
|
||||
+ struct test
|
||||
+ {
|
||||
+ const char *mode;
|
||||
+ int fd_mode;
|
||||
+ } test_modes[] = {
|
||||
+ {"a", O_WRONLY},
|
||||
+ {"a+", O_RDWR}
|
||||
+ };
|
||||
+
|
||||
+ for (int j = 0; j < 2; j++)
|
||||
+ {
|
||||
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
|
||||
+ {
|
||||
+ printf ("\tappend: %s (file, \"%s\"): ", j == 0 ? "fopen" : "fdopen",
|
||||
+ test_modes[i].mode);
|
||||
+
|
||||
+ if (j == 0)
|
||||
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
|
||||
+ else
|
||||
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
|
||||
+ test_modes[i].mode);
|
||||
+
|
||||
+ if (ret != 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Write some data. */
|
||||
+ size_t written = fputs_func (data, fp);
|
||||
+
|
||||
+ if (written == EOF)
|
||||
+ {
|
||||
+ printf ("fputs[1] failed to write all data\n");
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Verify that the offset points to the end of the file. */
|
||||
+ long offset = ftell (fp);
|
||||
+ file_len += data_len;
|
||||
+
|
||||
+ if (offset != file_len)
|
||||
+ {
|
||||
+ printf ("Incorrect offset. Expected %zu, but got %ld\n",
|
||||
+ file_len, offset);
|
||||
+
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+
|
||||
+ printf ("offset = %ld\n", offset);
|
||||
+ fclose (fp);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_one_test (const char *filename)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ ret |= do_ftell_test (filename);
|
||||
+ ret |= do_write_test (filename);
|
||||
+ ret |= do_append_test (filename);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ FILE *fp = NULL;
|
||||
+ char *filename;
|
||||
+ size_t written;
|
||||
+ int fd = create_temp_file ("tst-active-handler-tmp.", &filename);
|
||||
+
|
||||
+ if (fd == -1)
|
||||
+ {
|
||||
+ printf ("create_temp_file: %m\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ fp = fdopen (fd, "w");
|
||||
+ if (fp == NULL)
|
||||
+ {
|
||||
+ printf ("fdopen[0]: %m\n");
|
||||
+ close (fd);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ data = char_data;
|
||||
+ data_len = strlen (char_data);
|
||||
+ file_len = strlen (char_data);
|
||||
+ written = fputs (data, fp);
|
||||
+
|
||||
+ if (written == EOF)
|
||||
+ {
|
||||
+ printf ("fputs[1] failed to write data\n");
|
||||
+ ret = 1;
|
||||
+ }
|
||||
+
|
||||
+ fclose (fp);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Tests for regular files. */
|
||||
+ puts ("Regular mode:");
|
||||
+ fputs_func = (fputs_func_t) fputs;
|
||||
+ data = char_data;
|
||||
+ data_len = strlen (char_data);
|
||||
+ ret |= do_one_test (filename);
|
||||
+
|
||||
+ /* Truncate the file before repeating the tests in wide mode. */
|
||||
+ fp = fopen (filename, "w");
|
||||
+ if (fp == NULL)
|
||||
+ {
|
||||
+ printf ("fopen failed %m\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ fclose (fp);
|
||||
+
|
||||
+ /* Tests for wide files. */
|
||||
+ puts ("Wide mode:");
|
||||
+ if (setlocale (LC_ALL, "en_US.UTF-8") == NULL)
|
||||
+ {
|
||||
+ printf ("Cannot set en_US.UTF-8 locale.\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ fputs_func = (fputs_func_t) fputws;
|
||||
+ data = wide_data;
|
||||
+ data_len = wcslen (wide_data);
|
||||
+ ret |= do_one_test (filename);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
diff --git a/libio/wfileops.c b/libio/wfileops.c
|
||||
index 9cebe77..eda7828 100644
|
||||
--- a/libio/wfileops.c
|
||||
+++ b/libio/wfileops.c
|
||||
@@ -596,29 +596,22 @@ done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
-_IO_off64_t
|
||||
-_IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
- _IO_FILE *fp;
|
||||
- _IO_off64_t offset;
|
||||
- int dir;
|
||||
- int mode;
|
||||
+static _IO_off64_t
|
||||
+do_ftell_wide (_IO_FILE *fp)
|
||||
{
|
||||
- _IO_off64_t result;
|
||||
- _IO_off64_t delta, new_offset;
|
||||
- long int count;
|
||||
- /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
|
||||
- offset of the underlying file must be exact. */
|
||||
- int must_be_exact = ((fp->_wide_data->_IO_read_base
|
||||
- == fp->_wide_data->_IO_read_end)
|
||||
- && (fp->_wide_data->_IO_write_base
|
||||
- == fp->_wide_data->_IO_write_ptr));
|
||||
+ _IO_off64_t result, offset = 0;
|
||||
|
||||
- bool was_writing = ((fp->_wide_data->_IO_write_ptr
|
||||
- > fp->_wide_data->_IO_write_base)
|
||||
- || _IO_in_put_mode (fp));
|
||||
-
|
||||
- if (mode == 0)
|
||||
+ /* No point looking for offsets in the buffer if it hasn't even been
|
||||
+ allocated. */
|
||||
+ if (fp->_wide_data->_IO_buf_base != NULL)
|
||||
{
|
||||
+ const wchar_t *wide_read_base;
|
||||
+ const wchar_t *wide_read_ptr;
|
||||
+ const wchar_t *wide_read_end;
|
||||
+ bool was_writing = ((fp->_wide_data->_IO_write_ptr
|
||||
+ > fp->_wide_data->_IO_write_base)
|
||||
+ || _IO_in_put_mode (fp));
|
||||
+
|
||||
/* XXX For wide stream with backup store it is not very
|
||||
reasonable to determine the offset. The pushed-back
|
||||
character might require a state change and we need not be
|
||||
@@ -633,14 +626,117 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- /* There is no more data in the backup buffer. We can
|
||||
- switch back. */
|
||||
- _IO_switch_to_main_wget_area (fp);
|
||||
+ /* Nothing in the backup store, so note the backed up pointers
|
||||
+ without changing the state. */
|
||||
+ wide_read_base = fp->_wide_data->_IO_save_base;
|
||||
+ wide_read_ptr = wide_read_base;
|
||||
+ wide_read_end = fp->_wide_data->_IO_save_end;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ wide_read_base = fp->_wide_data->_IO_read_base;
|
||||
+ wide_read_ptr = fp->_wide_data->_IO_read_ptr;
|
||||
+ wide_read_end = fp->_wide_data->_IO_read_end;
|
||||
}
|
||||
|
||||
- dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
|
||||
+ struct _IO_codecvt *cv = fp->_codecvt;
|
||||
+ int clen = (*cv->__codecvt_do_encoding) (cv);
|
||||
+
|
||||
+ if (!was_writing)
|
||||
+ {
|
||||
+ if (clen > 0)
|
||||
+ {
|
||||
+ offset -= (wide_read_end - wide_read_ptr) * clen;
|
||||
+ offset -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ int nread;
|
||||
+
|
||||
+ size_t delta = wide_read_ptr - wide_read_base;
|
||||
+ __mbstate_t state = fp->_wide_data->_IO_last_state;
|
||||
+ nread = (*cv->__codecvt_do_length) (cv, &state,
|
||||
+ fp->_IO_read_base,
|
||||
+ fp->_IO_read_end, delta);
|
||||
+ offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (clen > 0)
|
||||
+ offset += (fp->_wide_data->_IO_write_ptr
|
||||
+ - fp->_wide_data->_IO_write_base) * clen;
|
||||
+ else
|
||||
+ {
|
||||
+ size_t delta = (fp->_wide_data->_IO_write_ptr
|
||||
+ - fp->_wide_data->_IO_write_base);
|
||||
+
|
||||
+ /* Allocate enough space for the conversion. */
|
||||
+ size_t outsize = delta * sizeof (wchar_t);
|
||||
+ char *out = malloc (outsize);
|
||||
+ char *outstop = out;
|
||||
+ const wchar_t *in = fp->_wide_data->_IO_write_base;
|
||||
+
|
||||
+ enum __codecvt_result status;
|
||||
+
|
||||
+ __mbstate_t state = fp->_wide_data->_IO_last_state;
|
||||
+ status = (*cv->__codecvt_do_out) (cv, &state,
|
||||
+ in, in + delta, &in,
|
||||
+ out, out + outsize, &outstop);
|
||||
+
|
||||
+ /* We don't check for __codecvt_partial because it can be
|
||||
+ returned on one of two conditions: either the output
|
||||
+ buffer is full or the input sequence is incomplete. We
|
||||
+ take care to allocate enough buffer and our input
|
||||
+ sequences must be complete since they are accepted as
|
||||
+ wchar_t; if not, then that is an error. */
|
||||
+ if (__glibc_unlikely (status != __codecvt_ok))
|
||||
+ return WEOF;
|
||||
+
|
||||
+ offset += outstop - out;
|
||||
+ }
|
||||
+
|
||||
+ /* _IO_read_end coincides with fp._offset, so the actual file position
|
||||
+ is fp._offset - (_IO_read_end - new_write_ptr). */
|
||||
+ offset -= fp->_IO_read_end - fp->_IO_write_ptr;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ result = get_file_offset (fp);
|
||||
+
|
||||
+ if (result == EOF)
|
||||
+ return result;
|
||||
+
|
||||
+ result += offset;
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+_IO_off64_t
|
||||
+_IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
+ _IO_FILE *fp;
|
||||
+ _IO_off64_t offset;
|
||||
+ int dir;
|
||||
+ int mode;
|
||||
+{
|
||||
+ _IO_off64_t result;
|
||||
+ _IO_off64_t delta, new_offset;
|
||||
+ long int count;
|
||||
+
|
||||
+ if (mode == 0)
|
||||
+ return do_ftell_wide (fp);
|
||||
+
|
||||
+ /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
|
||||
+ offset of the underlying file must be exact. */
|
||||
+ int must_be_exact = ((fp->_wide_data->_IO_read_base
|
||||
+ == fp->_wide_data->_IO_read_end)
|
||||
+ && (fp->_wide_data->_IO_write_base
|
||||
+ == fp->_wide_data->_IO_write_ptr));
|
||||
+
|
||||
+ bool was_writing = ((fp->_wide_data->_IO_write_ptr
|
||||
+ > fp->_wide_data->_IO_write_base)
|
||||
+ || _IO_in_put_mode (fp));
|
||||
+
|
||||
/* Flush unwritten characters.
|
||||
(This may do an unneeded write if we seek within the buffer.
|
||||
But to be able to switch to reading, we would need to set
|
||||
@@ -648,7 +744,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
which assumes file_ptr() is eGptr. Anyway, since we probably
|
||||
end up flushing when we close(), it doesn't make much difference.)
|
||||
FIXME: simulate mem-mapped files. */
|
||||
- else if (was_writing && _IO_switch_to_wget_mode (fp))
|
||||
+ if (was_writing && _IO_switch_to_wget_mode (fp))
|
||||
return WEOF;
|
||||
|
||||
if (fp->_wide_data->_IO_buf_base == NULL)
|
||||
@@ -693,7 +789,6 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
{
|
||||
int nread;
|
||||
|
||||
- flushed:
|
||||
delta = (fp->_wide_data->_IO_read_ptr
|
||||
- fp->_wide_data->_IO_read_base);
|
||||
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
|
||||
@@ -706,80 +801,9 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
|
||||
}
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- char *new_write_ptr = fp->_IO_write_ptr;
|
||||
-
|
||||
- if (clen > 0)
|
||||
- offset += (fp->_wide_data->_IO_write_ptr
|
||||
- - fp->_wide_data->_IO_write_base) / clen;
|
||||
- else
|
||||
- {
|
||||
- enum __codecvt_result status = __codecvt_ok;
|
||||
- delta = (fp->_wide_data->_IO_write_ptr
|
||||
- - fp->_wide_data->_IO_write_base);
|
||||
- const wchar_t *write_base = fp->_wide_data->_IO_write_base;
|
||||
-
|
||||
- /* FIXME: This actually ends up in two iterations of conversion,
|
||||
- one here and the next when the buffer actually gets flushed.
|
||||
- It may be possible to optimize this in future so that
|
||||
- wdo_write identifies already converted content and does not
|
||||
- redo it. In any case, this is much better than having to
|
||||
- flush buffers for every ftell. */
|
||||
- do
|
||||
- {
|
||||
- /* There is not enough space in the buffer to do the entire
|
||||
- conversion, so there is no point trying to avoid the
|
||||
- buffer flush. Just do it and go back to how it was with
|
||||
- the read mode. */
|
||||
- if (status == __codecvt_partial
|
||||
- || (delta > 0 && new_write_ptr == fp->_IO_buf_end))
|
||||
- {
|
||||
- if (_IO_switch_to_wget_mode (fp))
|
||||
- return WEOF;
|
||||
- goto flushed;
|
||||
- }
|
||||
-
|
||||
- const wchar_t *new_wbase = fp->_wide_data->_IO_write_base;
|
||||
- fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
|
||||
- status = (*cv->__codecvt_do_out) (cv,
|
||||
- &fp->_wide_data->_IO_state,
|
||||
- write_base,
|
||||
- write_base + delta,
|
||||
- &new_wbase,
|
||||
- new_write_ptr,
|
||||
- fp->_IO_buf_end,
|
||||
- &new_write_ptr);
|
||||
-
|
||||
- delta -= new_wbase - write_base;
|
||||
-
|
||||
- /* If there was an error, then return WEOF.
|
||||
- TODO: set buffer state. */
|
||||
- if (__glibc_unlikely (status == __codecvt_error))
|
||||
- return WEOF;
|
||||
- }
|
||||
- while (delta > 0);
|
||||
- }
|
||||
-
|
||||
- /* _IO_read_end coincides with fp._offset, so the actual file position
|
||||
- is fp._offset - (_IO_read_end - new_write_ptr). This is fine
|
||||
- even if fp._offset is not set, since fp->_IO_read_end is then at
|
||||
- _IO_buf_base and this adjustment is for unbuffered output. */
|
||||
- offset -= fp->_IO_read_end - new_write_ptr;
|
||||
- }
|
||||
|
||||
if (fp->_offset == _IO_pos_BAD)
|
||||
- {
|
||||
- if (mode != 0)
|
||||
- goto dumb;
|
||||
- else
|
||||
- {
|
||||
- result = _IO_SYSSEEK (fp, 0, dir);
|
||||
- if (result == EOF)
|
||||
- return result;
|
||||
- fp->_offset = result;
|
||||
- }
|
||||
- }
|
||||
+ goto dumb;
|
||||
|
||||
/* Make offset absolute, assuming current pointer is file_ptr(). */
|
||||
offset += fp->_offset;
|
||||
@@ -802,10 +826,6 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
}
|
||||
/* At this point, dir==_IO_seek_set. */
|
||||
|
||||
- /* If we are only interested in the current position we've found it now. */
|
||||
- if (mode == 0)
|
||||
- return offset;
|
||||
-
|
||||
/* If destination is within current buffer, optimize: */
|
||||
if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
|
||||
&& !_IO_in_backup (fp))
|
183
glibc-rh1069559-2.patch
Normal file
183
glibc-rh1069559-2.patch
Normal file
@ -0,0 +1,183 @@
|
||||
commit 4a68e8ded4fef2b00fbfc6baf1e79e46389871ca
|
||||
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Date: Thu Feb 20 15:55:16 2014 +0530
|
||||
|
||||
Use cached offset in ftell when reliable
|
||||
|
||||
The cached offset is reliable to use in ftell when the stream handle
|
||||
is active. We can consider a stream as being active when there is
|
||||
unbuffered data. However, even in this case, we can use the cached
|
||||
offset only when the stream is not being written to in a+ mode,
|
||||
because this case may have unbuffered data and a stale offset; the
|
||||
previous read could have sent it off somewhere other than the end of
|
||||
the file.
|
||||
|
||||
There were a couple of adjustments necessary to get this to work.
|
||||
Firstly, fdopen now ceases to use _IO_attach_fd because it sets the
|
||||
offset cache to the current file position. This is not correct
|
||||
because there could be changes to the file descriptor before the
|
||||
stream handle is activated, which would not get reflected.
|
||||
|
||||
A similar offset caching action is done in _IO_fwide, claiming that
|
||||
wide streams have 'problems' with the file offsets. There don't seem
|
||||
to be any obvious problems with not having the offset cache available,
|
||||
other than that it will have to be queried in a subsequent
|
||||
read/write/seek. I have removed this as well.
|
||||
|
||||
The testsuite passes successfully with these changes on x86_64.
|
||||
|
||||
diff --git a/libio/fileops.c b/libio/fileops.c
|
||||
index a177302..c44a5da 100644
|
||||
--- a/libio/fileops.c
|
||||
+++ b/libio/fileops.c
|
||||
@@ -952,12 +952,8 @@ get_file_offset (_IO_FILE *fp)
|
||||
static _IO_off64_t
|
||||
do_ftell (_IO_FILE *fp)
|
||||
{
|
||||
- _IO_off64_t result;
|
||||
-
|
||||
- result = get_file_offset (fp);
|
||||
-
|
||||
- if (result == EOF)
|
||||
- return result;
|
||||
+ _IO_off64_t result = 0;
|
||||
+ bool use_cached_offset = false;
|
||||
|
||||
/* No point looking at unflushed data if we haven't allocated buffers
|
||||
yet. */
|
||||
@@ -971,8 +967,34 @@ do_ftell (_IO_FILE *fp)
|
||||
result -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
else
|
||||
result += fp->_IO_write_ptr - fp->_IO_read_end;
|
||||
+
|
||||
+ /* It is safe to use the cached offset when available if there is
|
||||
+ unbuffered data (indicating that the file handle is active) and the
|
||||
+ handle is not for a file open in a+ mode. The latter condition is
|
||||
+ because there could be a scenario where there is a switch from read
|
||||
+ mode to write mode using an fseek to an arbitrary position. In this
|
||||
+ case, there would be unbuffered data due to be appended to the end of
|
||||
+ the file, but the offset may not necessarily be the end of the
|
||||
+ file. It is fine to use the cached offset when the a+ stream is in
|
||||
+ read mode though, since the offset is maintained correctly in that
|
||||
+ case. Note that this is not a comprehensive set of cases when the
|
||||
+ offset is reliable. The offset may be reliable even in some cases
|
||||
+ where there is no buffered input and the handle is active, but it's
|
||||
+ just that we don't have a way to identify that condition reliably. */
|
||||
+ use_cached_offset = (result != 0 && fp->_offset != _IO_pos_BAD
|
||||
+ && ((fp->_flags & (_IO_IS_APPENDING | _IO_NO_READS))
|
||||
+ == (_IO_IS_APPENDING | _IO_NO_READS)
|
||||
+ && was_writing));
|
||||
}
|
||||
|
||||
+ if (use_cached_offset)
|
||||
+ result += fp->_offset;
|
||||
+ else
|
||||
+ result += get_file_offset (fp);
|
||||
+
|
||||
+ if (result == EOF)
|
||||
+ return result;
|
||||
+
|
||||
if (result < 0)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
diff --git a/libio/iofdopen.c b/libio/iofdopen.c
|
||||
index 066ff19..4525f0f 100644
|
||||
--- a/libio/iofdopen.c
|
||||
+++ b/libio/iofdopen.c
|
||||
@@ -141,9 +141,6 @@ _IO_new_fdopen (fd, mode)
|
||||
#ifdef _IO_MTSAFE_IO
|
||||
new_f->fp.file._lock = &new_f->lock;
|
||||
#endif
|
||||
- /* Set up initially to use the `maybe_mmap' jump tables rather than using
|
||||
- __fopen_maybe_mmap to do it, because we need them in place before we
|
||||
- call _IO_file_attach or else it will allocate a buffer immediately. */
|
||||
_IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd,
|
||||
#ifdef _G_HAVE_MMAP
|
||||
(use_mmap && (read_write & _IO_NO_WRITES))
|
||||
@@ -159,13 +156,10 @@ _IO_new_fdopen (fd, mode)
|
||||
#if !_IO_UNIFIED_JUMPTABLES
|
||||
new_f->fp.vtable = NULL;
|
||||
#endif
|
||||
- if (_IO_file_attach ((_IO_FILE *) &new_f->fp, fd) == NULL)
|
||||
- {
|
||||
- _IO_setb (&new_f->fp.file, NULL, NULL, 0);
|
||||
- _IO_un_link (&new_f->fp);
|
||||
- free (new_f);
|
||||
- return NULL;
|
||||
- }
|
||||
+ /* We only record the fd because _IO_file_init will have unset the offset.
|
||||
+ We don't need to get the current offset in the file now since it could
|
||||
+ change between now and when the handle is activated. */
|
||||
+ new_f->fp.file._fileno = fd;
|
||||
new_f->fp.file._flags &= ~_IO_DELETE_DONT_CLOSE;
|
||||
|
||||
_IO_mask_flags (&new_f->fp.file, read_write,
|
||||
diff --git a/libio/iofwide.c b/libio/iofwide.c
|
||||
index 5cff632..64187e4 100644
|
||||
--- a/libio/iofwide.c
|
||||
+++ b/libio/iofwide.c
|
||||
@@ -199,12 +199,6 @@ _IO_fwide (fp, mode)
|
||||
|
||||
/* From now on use the wide character callback functions. */
|
||||
((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;
|
||||
-
|
||||
- /* One last twist: we get the current stream position. The wide
|
||||
- char streams have much more problems with not knowing the
|
||||
- current position and so we should disable the optimization
|
||||
- which allows the functions without knowing the position. */
|
||||
- fp->_offset = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
|
||||
}
|
||||
|
||||
/* Set the mode now. */
|
||||
diff --git a/libio/wfileops.c b/libio/wfileops.c
|
||||
index eda7828..651f5ce 100644
|
||||
--- a/libio/wfileops.c
|
||||
+++ b/libio/wfileops.c
|
||||
@@ -600,6 +600,7 @@ static _IO_off64_t
|
||||
do_ftell_wide (_IO_FILE *fp)
|
||||
{
|
||||
_IO_off64_t result, offset = 0;
|
||||
+ bool use_cached_offset = false;
|
||||
|
||||
/* No point looking for offsets in the buffer if it hasn't even been
|
||||
allocated. */
|
||||
@@ -696,13 +697,36 @@ do_ftell_wide (_IO_FILE *fp)
|
||||
offset += outstop - out;
|
||||
}
|
||||
|
||||
- /* _IO_read_end coincides with fp._offset, so the actual file position
|
||||
- is fp._offset - (_IO_read_end - new_write_ptr). */
|
||||
+ /* _IO_read_end coincides with fp._offset, so the actual file
|
||||
+ position is fp._offset - (_IO_read_end - new_write_ptr). */
|
||||
offset -= fp->_IO_read_end - fp->_IO_write_ptr;
|
||||
+
|
||||
}
|
||||
+
|
||||
+ /* It is safe to use the cached offset when available if there is
|
||||
+ unbuffered data (indicating that the file handle is active) and
|
||||
+ the handle is not for a file open in a+ mode. The latter
|
||||
+ condition is because there could be a scenario where there is a
|
||||
+ switch from read mode to write mode using an fseek to an arbitrary
|
||||
+ position. In this case, there would be unbuffered data due to be
|
||||
+ appended to the end of the file, but the offset may not
|
||||
+ necessarily be the end of the file. It is fine to use the cached
|
||||
+ offset when the a+ stream is in read mode though, since the offset
|
||||
+ is maintained correctly in that case. Note that this is not a
|
||||
+ comprehensive set of cases when the offset is reliable. The
|
||||
+ offset may be reliable even in some cases where there is no
|
||||
+ buffered input and the handle is active, but it's just that we
|
||||
+ don't have a way to identify that condition reliably. */
|
||||
+ use_cached_offset = (offset != 0 && fp->_offset != _IO_pos_BAD
|
||||
+ && ((fp->_flags & (_IO_IS_APPENDING | _IO_NO_READS))
|
||||
+ == (_IO_IS_APPENDING | _IO_NO_READS)
|
||||
+ && was_writing));
|
||||
}
|
||||
|
||||
- result = get_file_offset (fp);
|
||||
+ if (use_cached_offset)
|
||||
+ result = fp->_offset;
|
||||
+ else
|
||||
+ result = get_file_offset (fp);
|
||||
|
||||
if (result == EOF)
|
||||
return result;
|
@ -1,12 +1,3 @@
|
||||
Short description: Add syslog.target dependency.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-Fedora: #1070416
|
||||
Upstream status: not-needed
|
||||
|
||||
Fedora-specific changes to the nscd.service file.
|
||||
See also: glibc-nscd-sysconfig.patch.
|
||||
|
||||
--- a/nscd/nscd.service
|
||||
+++ b/nscd/nscd.service
|
||||
@@ -2,6 +2,7 @@
|
||||
|
@ -1,22 +0,0 @@
|
||||
Please see the following bug for a complete summary:
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1615608
|
||||
|
||||
Index: glibc-2.28/manual/startup.texi
|
||||
===================================================================
|
||||
--- glibc-2.28.orig/manual/startup.texi
|
||||
+++ glibc-2.28/manual/startup.texi
|
||||
@@ -1005,14 +1005,6 @@ This function actually terminates the pr
|
||||
intercept this signal; see @ref{Signal Handling}.
|
||||
@end deftypefun
|
||||
|
||||
-@c Put in by rms. Don't remove.
|
||||
-@cartouche
|
||||
-@strong{Future Change Warning:} Proposed Federal censorship regulations
|
||||
-may prohibit us from giving you information about the possibility of
|
||||
-calling this function. We would be required to say that this is not an
|
||||
-acceptable way of terminating a program.
|
||||
-@end cartouche
|
||||
-
|
||||
@node Termination Internals
|
||||
@subsection Termination Internals
|
||||
|
@ -1,14 +1,3 @@
|
||||
Short description: Add UCS-2 aliases.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #697421
|
||||
Upstream status: https://sourceware.org/ml/libc-alpha/2012-12/msg00103.html
|
||||
|
||||
This is a Fedora-specific change to include new aliases for UCS-2
|
||||
data for gconv used by a certain class of users. This should be
|
||||
revisited at some point to determine if those users are just using
|
||||
UTF-8 at this point.
|
||||
|
||||
diff -rup a/iconvdata/gconv-modules b/iconvdata/gconv-modules
|
||||
--- a/iconvdata/gconv-modules 2010-05-04 05:27:23.000000000 -0600
|
||||
+++ b/iconvdata/gconv-modules 2012-01-26 10:58:24.181895489 -0700
|
||||
|
@ -1,14 +1,3 @@
|
||||
Short description: Work ld.so --verify crash on debuginfo files.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #741105, #767146
|
||||
Upstream status: not-needed
|
||||
|
||||
This change is designed to work around running ld.so on a debuginfo
|
||||
file. This is the wrong fix for this problem and should be dropped.
|
||||
The correct solution is to mark debuginfo files as new types of
|
||||
ELF files.
|
||||
|
||||
Index: glibc-2.22-386-g95e8397/elf/dl-load.c
|
||||
===================================================================
|
||||
--- glibc-2.22-386-g95e8397.orig/elf/dl-load.c
|
||||
|
@ -1,16 +1,3 @@
|
||||
Short description: fnmatch() fails with MBCS.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #819430, #826149, #826151
|
||||
Bug-Upstream: #14185
|
||||
Upstream status: not-submitted
|
||||
|
||||
fnmatch() fails when '*' wildcard is applied on the file name
|
||||
containing multi-byte character(s)
|
||||
|
||||
This needs to be reviewed thoroughly and go upstream with a
|
||||
new test case.
|
||||
|
||||
diff -Nrup a/posix/fnmatch.c b/posix/fnmatch.c
|
||||
--- a/posix/fnmatch.c 2012-01-01 07:16:32.000000000 -0500
|
||||
+++ b/posix/fnmatch.c 2012-05-23 14:14:29.099461189 -0400
|
||||
|
13
glibc-rh825061.patch
Normal file
13
glibc-rh825061.patch
Normal file
@ -0,0 +1,13 @@
|
||||
diff -rup a/manual/Makefile b/manual/Makefile
|
||||
--- a/manual/Makefile 2012-05-20 19:47:38.000000000 -0600
|
||||
+++ b/manual/Makefile 2012-05-29 22:23:33.920428631 -0600
|
||||
@@ -129,7 +129,8 @@ $(objpfx)%.c.texi: examples/%.c
|
||||
mv -f $@.new $@
|
||||
|
||||
$(objpfx)%.info: %.texinfo
|
||||
- LANGUAGE=C LC_ALL=C $(MAKEINFO) -P $(objpfx) --output=$@ $<
|
||||
+ LANGUAGE=C LC_ALL=C $(MAKEINFO) -P $(objpfx) --output=`basename $@` $<
|
||||
+ mv `basename $@`* $(objpfx)
|
||||
|
||||
$(objpfx)%.dvi: %.texinfo
|
||||
cd $(objpfx);$(TEXI2DVI) -I $(shell cd $(<D) && pwd) --output=$@ \
|
@ -1,16 +1,6 @@
|
||||
Short description: Fix newlocale error return.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #832516
|
||||
Bug-Fedora: #827510
|
||||
Bug-Upstream: #14247
|
||||
Upstream status: not-submitted
|
||||
|
||||
This needs to go upstream right away to fix the error case for
|
||||
newlocale not correctly returning an error.
|
||||
|
||||
2012-06-14 Jeff Law <law@redhat.com>
|
||||
|
||||
|
||||
* locale/loadlocale.c (_nl_load_locale): Delay setting
|
||||
file->decided until we have successfully loaded the file's
|
||||
data.
|
||||
@ -26,7 +16,7 @@ index e3fa187..9fd9216 100644
|
||||
- file->decided = 1;
|
||||
file->data = NULL;
|
||||
|
||||
fd = __open_nocancel (file->filename, O_RDONLY | O_CLOEXEC);
|
||||
fd = open_not_cancel_2 (file->filename, O_RDONLY | O_CLOEXEC);
|
||||
@@ -278,6 +277,7 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
|
||||
newdata->alloc = alloc;
|
||||
|
||||
|
181
glibc-rh952799.patch
Normal file
181
glibc-rh952799.patch
Normal file
@ -0,0 +1,181 @@
|
||||
#
|
||||
# Red Hat BZ:
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=816647
|
||||
#
|
||||
# ChangeLog
|
||||
#
|
||||
#2013-04-30 Patsy Franklin <pfrankli@redhat.com>
|
||||
#
|
||||
# * iconv/gconv_cache.c (find_module): Demangle init_fct before
|
||||
# checking for NULL. Mangle __btowc_fct if init_fct is non-NULL.
|
||||
# * iconv/gconv_db.c (free_derivation): Check that __shlib_handle
|
||||
# is non-NULL before demangling the end_fct. Check for NULL
|
||||
# end_fct after demangling.
|
||||
# (__gconv_release_step): Demangle the end_fct before checking
|
||||
# it for NULL. Remove assert on __shlibc_handle != NULL.
|
||||
# (gen_steps): Don't check btowc_fct for NULL before mangling.
|
||||
# Demangle init_fct before checking for NULL.
|
||||
# (increment_counter): Likewise
|
||||
# * gconv_dl.c (__gconv_find_shlib): Don't check init_fct or
|
||||
# end_fct for NULL before mangling.
|
||||
# * wcsmbs/btowc.c (__btowc): Demangle btowc_fct before checking
|
||||
# for NULL.
|
||||
#
|
||||
diff -Nrup a/iconv/gconv_cache.c b/iconv/gconv_cache.c
|
||||
--- a/iconv/gconv_cache.c 2012-12-24 22:02:13.000000000 -0500
|
||||
+++ b/iconv/gconv_cache.c 2013-04-30 06:43:24.788684270 -0400
|
||||
@@ -207,17 +207,16 @@ find_module (const char *directory, cons
|
||||
result->__data = NULL;
|
||||
|
||||
/* Call the init function. */
|
||||
- if (result->__init_fct != NULL)
|
||||
- {
|
||||
- __gconv_init_fct init_fct = result->__init_fct;
|
||||
+ __gconv_init_fct init_fct = result->__init_fct;
|
||||
#ifdef PTR_DEMANGLE
|
||||
- PTR_DEMANGLE (init_fct);
|
||||
+ PTR_DEMANGLE (init_fct);
|
||||
#endif
|
||||
+ if (init_fct != NULL)
|
||||
+ {
|
||||
status = DL_CALL_FCT (init_fct, (result));
|
||||
|
||||
#ifdef PTR_MANGLE
|
||||
- if (result->__btowc_fct != NULL)
|
||||
- PTR_MANGLE (result->__btowc_fct);
|
||||
+ PTR_MANGLE (result->__btowc_fct);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
diff -Nrup a/iconv/gconv_db.c b/iconv/gconv_db.c
|
||||
--- a/iconv/gconv_db.c 2012-12-24 22:02:13.000000000 -0500
|
||||
+++ b/iconv/gconv_db.c 2013-04-30 06:37:16.886521576 -0400
|
||||
@@ -179,16 +179,15 @@ free_derivation (void *p)
|
||||
size_t cnt;
|
||||
|
||||
for (cnt = 0; cnt < deriv->nsteps; ++cnt)
|
||||
- if (deriv->steps[cnt].__counter > 0
|
||||
- && deriv->steps[cnt].__end_fct != NULL)
|
||||
+ if ((deriv->steps[cnt].__counter > 0)
|
||||
+ && (deriv->steps[cnt].__shlib_handle != NULL))
|
||||
{
|
||||
- assert (deriv->steps[cnt].__shlib_handle != NULL);
|
||||
-
|
||||
__gconv_end_fct end_fct = deriv->steps[cnt].__end_fct;
|
||||
#ifdef PTR_DEMANGLE
|
||||
PTR_DEMANGLE (end_fct);
|
||||
#endif
|
||||
- DL_CALL_FCT (end_fct, (&deriv->steps[cnt]));
|
||||
+ if (end_fct != NULL)
|
||||
+ DL_CALL_FCT (end_fct, (&deriv->steps[cnt]));
|
||||
}
|
||||
|
||||
/* Free the name strings. */
|
||||
@@ -212,16 +211,12 @@ __gconv_release_step (struct __gconv_ste
|
||||
if (step->__shlib_handle != NULL && --step->__counter == 0)
|
||||
{
|
||||
/* Call the destructor. */
|
||||
- if (step->__end_fct != NULL)
|
||||
- {
|
||||
- assert (step->__shlib_handle != NULL);
|
||||
-
|
||||
- __gconv_end_fct end_fct = step->__end_fct;
|
||||
+ __gconv_end_fct end_fct = step->__end_fct;
|
||||
#ifdef PTR_DEMANGLE
|
||||
- PTR_DEMANGLE (end_fct);
|
||||
+ PTR_DEMANGLE (end_fct);
|
||||
#endif
|
||||
- DL_CALL_FCT (end_fct, (step));
|
||||
- }
|
||||
+ if (end_fct != NULL)
|
||||
+ DL_CALL_FCT (end_fct, (step));
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
/* Release the loaded module. */
|
||||
@@ -293,13 +288,11 @@ gen_steps (struct derivation_step *best,
|
||||
|
||||
/* Call the init function. */
|
||||
__gconv_init_fct init_fct = result[step_cnt].__init_fct;
|
||||
- if (init_fct != NULL)
|
||||
- {
|
||||
- assert (result[step_cnt].__shlib_handle != NULL);
|
||||
-
|
||||
# ifdef PTR_DEMANGLE
|
||||
- PTR_DEMANGLE (init_fct);
|
||||
+ PTR_DEMANGLE (init_fct);
|
||||
# endif
|
||||
+ if (init_fct != NULL)
|
||||
+ {
|
||||
status = DL_CALL_FCT (init_fct, (&result[step_cnt]));
|
||||
|
||||
if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
|
||||
@@ -312,8 +305,7 @@ gen_steps (struct derivation_step *best,
|
||||
}
|
||||
|
||||
# ifdef PTR_MANGLE
|
||||
- if (result[step_cnt].__btowc_fct != NULL)
|
||||
- PTR_MANGLE (result[step_cnt].__btowc_fct);
|
||||
+ PTR_MANGLE (result[step_cnt].__btowc_fct);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
@@ -393,16 +385,15 @@ increment_counter (struct __gconv_step *
|
||||
|
||||
/* Call the init function. */
|
||||
__gconv_init_fct init_fct = step->__init_fct;
|
||||
- if (init_fct != NULL)
|
||||
- {
|
||||
#ifdef PTR_DEMANGLE
|
||||
- PTR_DEMANGLE (init_fct);
|
||||
+ PTR_DEMANGLE (init_fct);
|
||||
#endif
|
||||
+ if (init_fct != NULL)
|
||||
+ {
|
||||
DL_CALL_FCT (init_fct, (step));
|
||||
|
||||
#ifdef PTR_MANGLE
|
||||
- if (step->__btowc_fct != NULL)
|
||||
- PTR_MANGLE (step->__btowc_fct);
|
||||
+ PTR_MANGLE (step->__btowc_fct);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
diff -Nrup a/iconv/gconv_dl.c b/iconv/gconv_dl.c
|
||||
--- a/iconv/gconv_dl.c 2012-12-24 22:02:13.000000000 -0500
|
||||
+++ b/iconv/gconv_dl.c 2013-04-30 06:37:16.889521601 -0400
|
||||
@@ -132,10 +132,8 @@ __gconv_find_shlib (const char *name)
|
||||
|
||||
#ifdef PTR_MANGLE
|
||||
PTR_MANGLE (found->fct);
|
||||
- if (found->init_fct != NULL)
|
||||
- PTR_MANGLE (found->init_fct);
|
||||
- if (found->end_fct != NULL)
|
||||
- PTR_MANGLE (found->end_fct);
|
||||
+ PTR_MANGLE (found->init_fct);
|
||||
+ PTR_MANGLE (found->end_fct);
|
||||
#endif
|
||||
|
||||
/* We have succeeded in loading the shared object. */
|
||||
diff -Nrup a/wcsmbs/btowc.c b/wcsmbs/btowc.c
|
||||
--- a/wcsmbs/btowc.c 2012-12-24 22:02:13.000000000 -0500
|
||||
+++ b/wcsmbs/btowc.c 2013-04-30 06:37:16.891521619 -0400
|
||||
@@ -47,15 +47,15 @@ __btowc (c)
|
||||
/* Get the conversion functions. */
|
||||
fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
|
||||
__gconv_btowc_fct btowc_fct = fcts->towc->__btowc_fct;
|
||||
+#ifdef PTR_DEMANGLE
|
||||
+ if (fcts->towc->__shlib_handle != NULL)
|
||||
+ PTR_DEMANGLE (btowc_fct);
|
||||
+#endif
|
||||
|
||||
if (__builtin_expect (fcts->towc_nsteps == 1, 1)
|
||||
&& __builtin_expect (btowc_fct != NULL, 1))
|
||||
{
|
||||
/* Use the shortcut function. */
|
||||
-#ifdef PTR_DEMANGLE
|
||||
- if (fcts->towc->__shlib_handle != NULL)
|
||||
- PTR_DEMANGLE (btowc_fct);
|
||||
-#endif
|
||||
return DL_CALL_FCT (btowc_fct, (fcts->towc, (unsigned char) c));
|
||||
}
|
||||
else
|
4264
glibc.spec
4264
glibc.spec
File diff suppressed because it is too large
Load Diff
340
glibc_post_upgrade.c
Normal file
340
glibc_post_upgrade.c
Normal file
@ -0,0 +1,340 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <dirent.h>
|
||||
#include <stddef.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <elf.h>
|
||||
|
||||
#define verbose_exec(failcode, path...) \
|
||||
do \
|
||||
{ \
|
||||
char *const arr[] = { path, NULL }; \
|
||||
vexec (failcode, arr); \
|
||||
} while (0)
|
||||
|
||||
__attribute__((noinline)) void vexec (int failcode, char *const path[]);
|
||||
__attribute__((noinline)) void says (const char *str);
|
||||
__attribute__((noinline)) void sayn (long num);
|
||||
__attribute__((noinline)) void message (char *const path[]);
|
||||
__attribute__((noinline)) int check_elf (const char *name);
|
||||
|
||||
#ifdef __i386__
|
||||
static int
|
||||
is_ia64 (void)
|
||||
{
|
||||
unsigned int fl1, fl2;
|
||||
|
||||
/* See if we can use cpuid. */
|
||||
__asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
|
||||
"pushl %0; popfl; pushfl; popl %0; popfl"
|
||||
: "=&r" (fl1), "=&r" (fl2)
|
||||
: "i" (0x00200000));
|
||||
if (((fl1 ^ fl2) & 0x00200000) == 0)
|
||||
return 0;
|
||||
|
||||
/* Host supports cpuid. See if cpuid gives capabilities, try
|
||||
CPUID(0). Preserve %ebx and %ecx; cpuid insn clobbers these, we
|
||||
don't need their CPUID values here, and %ebx may be the PIC
|
||||
register. */
|
||||
__asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
|
||||
: "=a" (fl1) : "0" (0) : "edx", "cc");
|
||||
if (fl1 == 0)
|
||||
return 0;
|
||||
|
||||
/* Invoke CPUID(1), return %edx; caller can examine bits to
|
||||
determine what's supported. */
|
||||
__asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
|
||||
: "=d" (fl2), "=a" (fl1) : "1" (1) : "cc");
|
||||
return (fl2 & (1 << 30)) != 0;
|
||||
}
|
||||
#else
|
||||
#define is_ia64() 0
|
||||
#endif
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
struct stat statbuf;
|
||||
char initpath[256];
|
||||
|
||||
char buffer[4096];
|
||||
struct pref {
|
||||
char *p;
|
||||
int len;
|
||||
} prefix[] = { { "libc-", 5 }, { "libm-", 5 },
|
||||
{ "librt-", 6 }, { "libpthread-", 11 },
|
||||
{ "librtkaio-", 10 }, { "libthread_db-", 13 } };
|
||||
int i, j, fd;
|
||||
off_t base;
|
||||
ssize_t ret;
|
||||
#ifdef __i386__
|
||||
const char *remove_dirs[] = { "/lib/tls", "/lib/i686", "/lib/tls/i486", "/lib/tls/i586", "/lib/tls/i686" };
|
||||
#else
|
||||
#ifndef LIBTLS
|
||||
#define LIBTLS "/lib/tls"
|
||||
#endif
|
||||
const char *remove_dirs[] = { LIBTLS };
|
||||
#endif
|
||||
for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j)
|
||||
{
|
||||
size_t rmlen = strlen (remove_dirs[j]);
|
||||
fd = open (remove_dirs[j], O_RDONLY);
|
||||
if (fd >= 0
|
||||
&& (ret = getdirentries (fd, buffer, sizeof (buffer), &base))
|
||||
>= (ssize_t) offsetof (struct dirent, d_name))
|
||||
{
|
||||
for (base = 0; base + offsetof (struct dirent, d_name) < ret; )
|
||||
{
|
||||
struct dirent *d = (struct dirent *) (buffer + base);
|
||||
|
||||
for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
|
||||
if (! strncmp (d->d_name, prefix[i].p, prefix[i].len))
|
||||
{
|
||||
char *p = d->d_name + prefix[i].len;
|
||||
|
||||
while (*p == '.' || (*p >= '0' && *p <= '9')) p++;
|
||||
if (p[0] == 's' && p[1] == 'o' && p[2] == '\0'
|
||||
&& p + 3 - d->d_name
|
||||
< sizeof (initpath) - rmlen - 1)
|
||||
{
|
||||
memcpy (initpath, remove_dirs[j], rmlen);
|
||||
initpath[rmlen] = '/';
|
||||
strcpy (initpath + rmlen + 1, d->d_name);
|
||||
unlink (initpath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
base += d->d_reclen;
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
int ldsocfd = open (LD_SO_CONF, O_RDONLY);
|
||||
struct stat ldsocst;
|
||||
if (ldsocfd >= 0 && fstat (ldsocfd, &ldsocst) >= 0)
|
||||
{
|
||||
char p[ldsocst.st_size + 1];
|
||||
if (read (ldsocfd, p, ldsocst.st_size) == ldsocst.st_size)
|
||||
{
|
||||
p[ldsocst.st_size] = '\0';
|
||||
if (strstr (p, "include ld.so.conf.d/*.conf") == NULL)
|
||||
{
|
||||
close (ldsocfd);
|
||||
ldsocfd = open (LD_SO_CONF, O_WRONLY | O_TRUNC);
|
||||
if (ldsocfd >= 0)
|
||||
{
|
||||
size_t slen = strlen ("include ld.so.conf.d/*.conf\n");
|
||||
if (write (ldsocfd, "include ld.so.conf.d/*.conf\n", slen)
|
||||
!= slen
|
||||
|| write (ldsocfd, p, ldsocst.st_size) != ldsocst.st_size)
|
||||
_exit (109);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ldsocfd >= 0)
|
||||
close (ldsocfd);
|
||||
}
|
||||
|
||||
/* If installing bi-arch glibc, rpm sometimes doesn't unpack all files
|
||||
before running one of the lib's %post scriptlet. /sbin/ldconfig will
|
||||
then be run by the other arch's %post. */
|
||||
if (! access ("/sbin/ldconfig", X_OK))
|
||||
verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig");
|
||||
|
||||
if (! utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL))
|
||||
{
|
||||
#ifndef ICONVCONFIG
|
||||
#define ICONVCONFIG "/usr/sbin/iconvconfig"
|
||||
#endif
|
||||
char *iconv_cache = GCONV_MODULES_DIR"/gconv-modules.cache";
|
||||
char *iconv_dir = GCONV_MODULES_DIR;
|
||||
if (is_ia64 ())
|
||||
{
|
||||
iconv_cache = "/emul/ia32-linux"GCONV_MODULES_DIR"/gconv-modules.cache";
|
||||
iconv_dir = "/emul/ia32-linux"GCONV_MODULES_DIR;
|
||||
}
|
||||
verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig",
|
||||
"-o", iconv_cache,
|
||||
"--nostdlib", iconv_dir);
|
||||
}
|
||||
|
||||
/* Check if telinit is available and either SysVInit fifo,
|
||||
or upstart telinit. */
|
||||
if (access ("/sbin/telinit", X_OK)
|
||||
|| ((!!access ("/dev/initctl", F_OK))
|
||||
^ !access ("/sbin/initctl", X_OK)))
|
||||
_exit (0);
|
||||
|
||||
/* Check if we are not inside of some chroot, because we'd just
|
||||
timeout and leave /etc/initrunlvl.
|
||||
|
||||
On more modern systems this test is not sufficient to detect
|
||||
if we're in a chroot. */
|
||||
if (readlink ("/proc/1/exe", initpath, 256) <= 0 ||
|
||||
readlink ("/proc/1/root", initpath, 256) <= 0)
|
||||
_exit (0);
|
||||
|
||||
/* Here's another well known way to detect chroot, at least on an
|
||||
ext and xfs filesystems and assuming nothing mounted on the chroot's
|
||||
root. */
|
||||
if (stat ("/", &statbuf) != 0
|
||||
|| (statbuf.st_ino != 2
|
||||
&& statbuf.st_ino != 128))
|
||||
_exit (0);
|
||||
|
||||
if (check_elf ("/proc/1/exe"))
|
||||
verbose_exec (116, "/sbin/telinit", "/sbin/telinit", "u");
|
||||
|
||||
/* Check if we can safely condrestart sshd. */
|
||||
if (access ("/sbin/service", X_OK) == 0
|
||||
&& access ("/usr/sbin/sshd", X_OK) == 0
|
||||
&& access ("/etc/rc.d/init.d/sshd", X_OK) == 0
|
||||
&& access ("/bin/bash", X_OK) == 0)
|
||||
{
|
||||
if (check_elf ("/usr/sbin/sshd"))
|
||||
verbose_exec (-121, "/sbin/service", "/sbin/service", "sshd", "condrestart");
|
||||
}
|
||||
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
vexec (int failcode, char *const path[])
|
||||
{
|
||||
pid_t pid;
|
||||
int status, save_errno;
|
||||
int devnull = 0;
|
||||
|
||||
if (failcode < 0)
|
||||
{
|
||||
devnull = 1;
|
||||
failcode = -failcode;
|
||||
}
|
||||
pid = vfork ();
|
||||
if (pid == 0)
|
||||
{
|
||||
int fd;
|
||||
if (devnull && (fd = open ("/dev/null", O_WRONLY)) >= 0)
|
||||
{
|
||||
dup2 (fd, 1);
|
||||
dup2 (fd, 2);
|
||||
close (fd);
|
||||
}
|
||||
execv (path[0], path + 1);
|
||||
save_errno = errno;
|
||||
message (path);
|
||||
says (" exec failed with errno ");
|
||||
sayn (save_errno);
|
||||
says ("\n");
|
||||
_exit (failcode);
|
||||
}
|
||||
else if (pid < 0)
|
||||
{
|
||||
save_errno = errno;
|
||||
message (path);
|
||||
says (" fork failed with errno ");
|
||||
sayn (save_errno);
|
||||
says ("\n");
|
||||
_exit (failcode + 1);
|
||||
}
|
||||
if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
|
||||
{
|
||||
message (path);
|
||||
says (" child terminated abnormally\n");
|
||||
_exit (failcode + 2);
|
||||
}
|
||||
if (WEXITSTATUS (status))
|
||||
{
|
||||
message (path);
|
||||
says (" child exited with exit code ");
|
||||
sayn (WEXITSTATUS (status));
|
||||
says ("\n");
|
||||
_exit (WEXITSTATUS (status));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
says (const char *str)
|
||||
{
|
||||
write (1, str, strlen (str));
|
||||
}
|
||||
|
||||
void
|
||||
sayn (long num)
|
||||
{
|
||||
char string[sizeof (long) * 3 + 1];
|
||||
char *p = string + sizeof (string) - 1;
|
||||
|
||||
*p = '\0';
|
||||
if (num == 0)
|
||||
*--p = '0';
|
||||
else
|
||||
while (num)
|
||||
{
|
||||
*--p = '0' + num % 10;
|
||||
num = num / 10;
|
||||
}
|
||||
|
||||
says (p);
|
||||
}
|
||||
|
||||
void
|
||||
message (char *const path[])
|
||||
{
|
||||
says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
|
||||
says (path[0]);
|
||||
}
|
||||
|
||||
int
|
||||
check_elf (const char *name)
|
||||
{
|
||||
/* Play safe, if we can't open or read, assume it might be
|
||||
ELF for the current arch. */
|
||||
int ret = 1;
|
||||
int fd = open (name, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
Elf32_Ehdr ehdr;
|
||||
if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version))
|
||||
== offsetof (Elf32_Ehdr, e_version))
|
||||
{
|
||||
ret = 0;
|
||||
if (ehdr.e_ident[EI_CLASS]
|
||||
== (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32))
|
||||
{
|
||||
#if defined __i386__
|
||||
ret = ehdr.e_machine == EM_386;
|
||||
#elif defined __x86_64__
|
||||
ret = ehdr.e_machine == EM_X86_64;
|
||||
#elif defined __ia64__
|
||||
ret = ehdr.e_machine == EM_IA_64;
|
||||
#elif defined __powerpc64__
|
||||
ret = ehdr.e_machine == EM_PPC64;
|
||||
#elif defined __powerpc__
|
||||
ret = ehdr.e_machine == EM_PPC;
|
||||
#elif defined __s390__ || defined __s390x__
|
||||
ret = ehdr.e_machine == EM_S390;
|
||||
#elif defined __x86_64__
|
||||
ret = ehdr.e_machine == EM_X86_64;
|
||||
#elif defined __sparc__
|
||||
if (sizeof (long) == 8)
|
||||
ret = ehdr.e_machine == EM_SPARCV9;
|
||||
else
|
||||
ret = (ehdr.e_machine == EM_SPARC
|
||||
|| ehdr.e_machine == EM_SPARC32PLUS);
|
||||
#else
|
||||
ret = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
return ret;
|
||||
}
|
340
libc-lock.h
Normal file
340
libc-lock.h
Normal file
@ -0,0 +1,340 @@
|
||||
/* libc-internal interface for mutex locks. LinuxThreads version.
|
||||
Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _BITS_LIBC_LOCK_H
|
||||
#define _BITS_LIBC_LOCK_H 1
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* Mutex type. */
|
||||
#ifdef _IO_MTSAFE_IO
|
||||
typedef pthread_mutex_t __libc_lock_t;
|
||||
typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t;
|
||||
# ifdef __USE_UNIX98
|
||||
typedef pthread_rwlock_t __libc_rwlock_t;
|
||||
# else
|
||||
typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
|
||||
# endif
|
||||
typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
|
||||
#else
|
||||
typedef struct __libc_lock_opaque__ __libc_lock_t;
|
||||
typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
|
||||
typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
|
||||
#endif
|
||||
|
||||
/* Type for key to thread-specific data. */
|
||||
typedef pthread_key_t __libc_key_t;
|
||||
|
||||
/* Define a lock variable NAME with storage class CLASS. The lock must be
|
||||
initialized with __libc_lock_init before it can be used (or define it
|
||||
with __libc_lock_define_initialized, below). Use `extern' for CLASS to
|
||||
declare a lock defined in another module. In public structure
|
||||
definitions you must use a pointer to the lock structure (i.e., NAME
|
||||
begins with a `*'), because its storage size will not be known outside
|
||||
of libc. */
|
||||
#define __libc_lock_define(CLASS,NAME) \
|
||||
CLASS __libc_lock_t NAME;
|
||||
#define __libc_rwlock_define(CLASS,NAME) \
|
||||
CLASS __libc_rwlock_t NAME;
|
||||
#define __libc_lock_define_recursive(CLASS,NAME) \
|
||||
CLASS __libc_lock_recursive_t NAME;
|
||||
#define __rtld_lock_define_recursive(CLASS,NAME) \
|
||||
CLASS __rtld_lock_recursive_t NAME;
|
||||
|
||||
/* Define an initialized lock variable NAME with storage class CLASS.
|
||||
|
||||
For the C library we take a deeper look at the initializer. For
|
||||
this implementation all fields are initialized to zero. Therefore
|
||||
we don't initialize the variable which allows putting it into the
|
||||
BSS section. (Except on PA-RISC and other odd architectures, where
|
||||
initialized locks must be set to one due to the lack of normal
|
||||
atomic operations.) */
|
||||
|
||||
#if __LT_SPINLOCK_INIT == 0
|
||||
# define __libc_lock_define_initialized(CLASS,NAME) \
|
||||
CLASS __libc_lock_t NAME;
|
||||
#else
|
||||
# define __libc_lock_define_initialized(CLASS,NAME) \
|
||||
CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
#define __libc_rwlock_define_initialized(CLASS,NAME) \
|
||||
CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
|
||||
|
||||
/* Define an initialized recursive lock variable NAME with storage
|
||||
class CLASS. */
|
||||
#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
|
||||
CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
|
||||
#define _LIBC_LOCK_RECURSIVE_INITIALIZER \
|
||||
{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
|
||||
|
||||
#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
|
||||
CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
|
||||
#define _RTLD_LOCK_RECURSIVE_INITIALIZER \
|
||||
{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
|
||||
|
||||
#if defined __PIC__
|
||||
# define __libc_maybe_call(FUNC, ARGS, ELSE) \
|
||||
(__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
|
||||
_fn != NULL ? (*_fn) ARGS : ELSE; }))
|
||||
#else
|
||||
# define __libc_maybe_call(FUNC, ARGS, ELSE) \
|
||||
(FUNC != NULL ? FUNC ARGS : ELSE)
|
||||
#endif
|
||||
#define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE)
|
||||
|
||||
/* Initialize the named lock variable, leaving it in a consistent, unlocked
|
||||
state. */
|
||||
#define __libc_lock_init(NAME) \
|
||||
(__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0))
|
||||
#define __libc_rwlock_init(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0));
|
||||
|
||||
/* Same as last but this time we initialize a recursive mutex. */
|
||||
#define __libc_lock_init_recursive(NAME) \
|
||||
do { \
|
||||
if (__pthread_mutex_init != NULL) \
|
||||
{ \
|
||||
pthread_mutexattr_t __attr; \
|
||||
__pthread_mutexattr_init (&__attr); \
|
||||
__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \
|
||||
__pthread_mutex_init (&(NAME).mutex, &__attr); \
|
||||
__pthread_mutexattr_destroy (&__attr); \
|
||||
} \
|
||||
} while (0);
|
||||
#define __rtld_lock_init_recursive(NAME) \
|
||||
__libc_lock_init_recursive (NAME)
|
||||
|
||||
/* Finalize the named lock variable, which must be locked. It cannot be
|
||||
used again until __libc_lock_init is called again on it. This must be
|
||||
called on a lock variable before the containing storage is reused. */
|
||||
#define __libc_lock_fini(NAME) \
|
||||
(__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0));
|
||||
#define __libc_rwlock_fini(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0));
|
||||
|
||||
/* Finalize recursive named lock. */
|
||||
#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex)
|
||||
#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME)
|
||||
|
||||
/* Lock the named lock variable. */
|
||||
#define __libc_lock_lock(NAME) \
|
||||
(__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0));
|
||||
#define __libc_rwlock_rdlock(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0));
|
||||
#define __libc_rwlock_wrlock(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0));
|
||||
|
||||
/* Lock the recursive named lock variable. */
|
||||
#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex)
|
||||
|
||||
/* Try to lock the named lock variable. */
|
||||
#define __libc_lock_trylock(NAME) \
|
||||
(__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0))
|
||||
#define __libc_rwlock_tryrdlock(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0))
|
||||
#define __libc_rwlock_trywrlock(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0))
|
||||
|
||||
/* Try to lock the recursive named lock variable. */
|
||||
#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex)
|
||||
#define __rtld_lock_trylock_recursive(NAME) \
|
||||
__libc_lock_trylock_recursive (NAME)
|
||||
|
||||
/* Unlock the named lock variable. */
|
||||
#define __libc_lock_unlock(NAME) \
|
||||
(__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0));
|
||||
#define __libc_rwlock_unlock(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0));
|
||||
|
||||
/* Unlock the recursive named lock variable. */
|
||||
#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex)
|
||||
|
||||
#define __rtld_lock_lock_recursive(NAME) __libc_lock_lock_recursive (NAME)
|
||||
#define __rtld_lock_unlock_recursive(NAME) __libc_lock_unlock_recursive (NAME)
|
||||
|
||||
/* Define once control variable. */
|
||||
#if PTHREAD_ONCE_INIT == 0
|
||||
/* Special case for static variables where we can avoid the initialization
|
||||
if it is zero. */
|
||||
# define __libc_once_define(CLASS, NAME) \
|
||||
CLASS pthread_once_t NAME
|
||||
#else
|
||||
# define __libc_once_define(CLASS, NAME) \
|
||||
CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
|
||||
#endif
|
||||
|
||||
/* Call handler iff the first call. */
|
||||
#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
|
||||
do { \
|
||||
if (__pthread_once != NULL) \
|
||||
__pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \
|
||||
else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \
|
||||
INIT_FUNCTION (); \
|
||||
(ONCE_CONTROL) = 2; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Start critical region with cleanup. */
|
||||
#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
|
||||
{ struct _pthread_cleanup_buffer _buffer; \
|
||||
int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \
|
||||
if (_avail) { \
|
||||
_pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \
|
||||
}
|
||||
|
||||
/* End critical region with cleanup. */
|
||||
#define __libc_cleanup_region_end(DOIT) \
|
||||
if (_avail) { \
|
||||
_pthread_cleanup_pop_restore (&_buffer, (DOIT)); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Sometimes we have to exit the block in the middle. */
|
||||
#define __libc_cleanup_end(DOIT) \
|
||||
if (_avail) { \
|
||||
_pthread_cleanup_pop_restore (&_buffer, (DOIT)); \
|
||||
}
|
||||
|
||||
#define __libc_cleanup_push(fct, arg) \
|
||||
{ struct _pthread_cleanup_buffer _buffer; \
|
||||
__libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0)
|
||||
|
||||
#define __libc_cleanup_pop(execute) \
|
||||
__libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \
|
||||
}
|
||||
|
||||
/* Create thread-specific key. */
|
||||
#define __libc_key_create(KEY, DESTRUCTOR) \
|
||||
(__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1))
|
||||
|
||||
/* Get thread-specific data. */
|
||||
#define __libc_getspecific(KEY) \
|
||||
(__libc_maybe_call (__pthread_getspecific, (KEY), NULL))
|
||||
|
||||
/* Set thread-specific data. */
|
||||
#define __libc_setspecific(KEY, VALUE) \
|
||||
(__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0))
|
||||
|
||||
|
||||
/* Register handlers to execute before and after `fork'. */
|
||||
#define __libc_atfork(PREPARE, PARENT, CHILD) \
|
||||
(__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0))
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
|
||||
void (*__routine) (void *),
|
||||
void *__arg) __THROW;
|
||||
|
||||
extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
|
||||
int __execute) __THROW;
|
||||
|
||||
|
||||
/* Functions that are used by this file and are internal to the GNU C
|
||||
library. */
|
||||
|
||||
extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
|
||||
__const pthread_mutexattr_t *__mutex_attr);
|
||||
|
||||
extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
|
||||
|
||||
extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
|
||||
|
||||
extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
|
||||
|
||||
extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
|
||||
|
||||
extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
|
||||
|
||||
extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
|
||||
|
||||
extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
|
||||
int __kind);
|
||||
|
||||
#ifdef __USE_UNIX98
|
||||
extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
|
||||
__const pthread_rwlockattr_t *__attr);
|
||||
|
||||
extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
|
||||
|
||||
extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
|
||||
|
||||
extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
|
||||
|
||||
extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
|
||||
|
||||
extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
|
||||
|
||||
extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
|
||||
#endif
|
||||
|
||||
extern int __pthread_key_create (pthread_key_t *__key,
|
||||
void (*__destr_function) (void *));
|
||||
|
||||
extern int __pthread_setspecific (pthread_key_t __key,
|
||||
__const void *__pointer);
|
||||
|
||||
extern void *__pthread_getspecific (pthread_key_t __key);
|
||||
|
||||
extern int __pthread_once (pthread_once_t *__once_control,
|
||||
void (*__init_routine) (void));
|
||||
|
||||
extern int __pthread_atfork (void (*__prepare) (void),
|
||||
void (*__parent) (void),
|
||||
void (*__child) (void));
|
||||
|
||||
__END_DECLS
|
||||
|
||||
/* Make the pthread functions weak so that we can elide them from
|
||||
single-threaded processes. */
|
||||
#ifndef __NO_WEAK_PTHREAD_ALIASES
|
||||
# pragma weak __pthread_mutex_init
|
||||
# pragma weak __pthread_mutex_destroy
|
||||
# pragma weak __pthread_mutex_lock
|
||||
# pragma weak __pthread_mutex_trylock
|
||||
# pragma weak __pthread_mutex_unlock
|
||||
# pragma weak __pthread_mutexattr_init
|
||||
# pragma weak __pthread_mutexattr_destroy
|
||||
# pragma weak __pthread_mutexattr_settype
|
||||
# pragma weak __pthread_rwlock_destroy
|
||||
# pragma weak __pthread_rwlock_rdlock
|
||||
# pragma weak __pthread_rwlock_tryrdlock
|
||||
# pragma weak __pthread_rwlock_wrlock
|
||||
# pragma weak __pthread_rwlock_trywrlock
|
||||
# pragma weak __pthread_rwlock_unlock
|
||||
# pragma weak __pthread_key_create
|
||||
# pragma weak __pthread_setspecific
|
||||
# pragma weak __pthread_getspecific
|
||||
# pragma weak __pthread_once
|
||||
# pragma weak __pthread_initialize
|
||||
# pragma weak __pthread_atfork
|
||||
# pragma weak _pthread_cleanup_push_defer
|
||||
# pragma weak _pthread_cleanup_pop_restore
|
||||
# pragma weak _pthread_cleanup_push
|
||||
# pragma weak _pthread_cleanup_pop
|
||||
#endif
|
||||
|
||||
/* We need portable names for some functions. E.g., when they are
|
||||
used as argument to __libc_cleanup_region_start. */
|
||||
#define __libc_mutex_unlock __pthread_mutex_unlock
|
||||
|
||||
#endif /* bits/libc-lock.h */
|
739
mem-avx512-2016-v4.patch
Normal file
739
mem-avx512-2016-v4.patch
Normal file
@ -0,0 +1,739 @@
|
||||
Posted upstream by Intel:
|
||||
|
||||
https://sourceware.org/ml/libc-alpha/2016-01/msg00337.html
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile
|
||||
index b2e31ef..d234f4a 100644
|
||||
--- a/sysdeps/x86_64/multiarch/Makefile
|
||||
+++ b/sysdeps/x86_64/multiarch/Makefile
|
||||
@@ -7,11 +7,12 @@ ifeq ($(subdir),string)
|
||||
|
||||
sysdep_routines += strncat-c stpncpy-c strncpy-c strcmp-ssse3 \
|
||||
strcmp-sse2-unaligned strncmp-ssse3 \
|
||||
- memcmp-sse4 memcpy-ssse3 \
|
||||
- memcpy-sse2-unaligned mempcpy-ssse3 \
|
||||
- memmove-ssse3 memcpy-ssse3-back mempcpy-ssse3-back \
|
||||
- memmove-avx-unaligned memcpy-avx-unaligned mempcpy-avx-unaligned \
|
||||
- memmove-ssse3-back strcasecmp_l-ssse3 \
|
||||
+ memcmp-sse4 memcpy-ssse3 memcpy-sse2-unaligned \
|
||||
+ memcpy-avx512-no-vzeroupper mempcpy-ssse3 memmove-ssse3 \
|
||||
+ memcpy-ssse3-back mempcpy-ssse3-back memmove-avx-unaligned \
|
||||
+ memcpy-avx-unaligned mempcpy-avx-unaligned \
|
||||
+ mempcpy-avx512-no-vzeroupper memmove-ssse3-back \
|
||||
+ memmove-avx512-no-vzeroupper strcasecmp_l-ssse3 \
|
||||
strncase_l-ssse3 strcat-ssse3 strncat-ssse3\
|
||||
strcpy-ssse3 strncpy-ssse3 stpcpy-ssse3 stpncpy-ssse3 \
|
||||
strcpy-sse2-unaligned strncpy-sse2-unaligned \
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index 5f600dc..d9ff016 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "init-arch.h"
|
||||
|
||||
/* Maximum number of IFUNC implementations. */
|
||||
-#define MAX_IFUNC 4
|
||||
+#define MAX_IFUNC 5
|
||||
|
||||
/* Fill ARRAY of MAX elements with IFUNC implementations for function
|
||||
NAME supported on target machine and return the number of valid
|
||||
@@ -46,9 +46,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
__memcmp_ssse3)
|
||||
IFUNC_IMPL_ADD (array, i, memcmp, 1, __memcmp_sse2))
|
||||
|
||||
- /* Support sysdeps/x86_64/multiarch/memmove_chk.S. */
|
||||
+ /* Support sysdeps/x86_64/multiarch/memmove_chk.c. */
|
||||
IFUNC_IMPL (i, name, __memmove_chk,
|
||||
IFUNC_IMPL_ADD (array, i, __memmove_chk,
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable),
|
||||
+ __memmove_chk_avx512_no_vzeroupper)
|
||||
+ IFUNC_IMPL_ADD (array, i, __memmove_chk,
|
||||
HAS_ARCH_FEATURE (AVX_Usable),
|
||||
__memmove_chk_avx_unaligned)
|
||||
IFUNC_IMPL_ADD (array, i, __memmove_chk,
|
||||
@@ -65,6 +68,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL_ADD (array, i, memmove,
|
||||
HAS_ARCH_FEATURE (AVX_Usable),
|
||||
__memmove_avx_unaligned)
|
||||
+ IFUNC_IMPL_ADD (array, i, memmove,
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable),
|
||||
+ __memmove_avx512_no_vzeroupper)
|
||||
IFUNC_IMPL_ADD (array, i, memmove, HAS_CPU_FEATURE (SSSE3),
|
||||
__memmove_ssse3_back)
|
||||
IFUNC_IMPL_ADD (array, i, memmove, HAS_CPU_FEATURE (SSSE3),
|
||||
@@ -254,6 +260,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/memcpy_chk.S. */
|
||||
IFUNC_IMPL (i, name, __memcpy_chk,
|
||||
IFUNC_IMPL_ADD (array, i, __memcpy_chk,
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable),
|
||||
+ __memcpy_chk_avx512_no_vzeroupper)
|
||||
+ IFUNC_IMPL_ADD (array, i, __memcpy_chk,
|
||||
HAS_ARCH_FEATURE (AVX_Usable),
|
||||
__memcpy_chk_avx_unaligned)
|
||||
IFUNC_IMPL_ADD (array, i, __memcpy_chk,
|
||||
@@ -274,12 +283,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
__memcpy_ssse3_back)
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, HAS_CPU_FEATURE (SSSE3),
|
||||
__memcpy_ssse3)
|
||||
+ IFUNC_IMPL_ADD (array, i, memcpy,
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable),
|
||||
+ __memcpy_avx512_no_vzeroupper)
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_sse2_unaligned)
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_sse2))
|
||||
|
||||
/* Support sysdeps/x86_64/multiarch/mempcpy_chk.S. */
|
||||
IFUNC_IMPL (i, name, __mempcpy_chk,
|
||||
IFUNC_IMPL_ADD (array, i, __mempcpy_chk,
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable),
|
||||
+ __mempcpy_chk_avx512_no_vzeroupper)
|
||||
+ IFUNC_IMPL_ADD (array, i, __mempcpy_chk,
|
||||
HAS_ARCH_FEATURE (AVX_Usable),
|
||||
__mempcpy_chk_avx_unaligned)
|
||||
IFUNC_IMPL_ADD (array, i, __mempcpy_chk,
|
||||
@@ -294,6 +309,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/mempcpy.S. */
|
||||
IFUNC_IMPL (i, name, mempcpy,
|
||||
IFUNC_IMPL_ADD (array, i, mempcpy,
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable),
|
||||
+ __mempcpy_avx512_no_vzeroupper)
|
||||
+ IFUNC_IMPL_ADD (array, i, mempcpy,
|
||||
HAS_ARCH_FEATURE (AVX_Usable),
|
||||
__mempcpy_avx_unaligned)
|
||||
IFUNC_IMPL_ADD (array, i, mempcpy, HAS_CPU_FEATURE (SSSE3),
|
||||
diff --git a/sysdeps/x86_64/multiarch/memcpy-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/memcpy-avx512-no-vzeroupper.S
|
||||
new file mode 100644
|
||||
index 0000000..1b2eb6d
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86_64/multiarch/memcpy-avx512-no-vzeroupper.S
|
||||
@@ -0,0 +1,414 @@
|
||||
+/* memcpy optimized with AVX512 for KNL hardware.
|
||||
+ Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sysdep.h>
|
||||
+
|
||||
+#if defined HAVE_AVX512_ASM_SUPPORT && IS_IN (libc) \
|
||||
+ && (defined SHARED \
|
||||
+ || defined USE_AS_MEMMOVE \
|
||||
+ || !defined USE_MULTIARCH)
|
||||
+
|
||||
+#include "asm-syntax.h"
|
||||
+#ifndef MEMCPY
|
||||
+# define MEMCPY __memcpy_avx512_no_vzeroupper
|
||||
+# define MEMCPY_CHK __memcpy_chk_avx512_no_vzeroupper
|
||||
+#endif
|
||||
+
|
||||
+ .section .text,"ax",@progbits
|
||||
+#if !defined USE_AS_BCOPY
|
||||
+ENTRY (MEMCPY_CHK)
|
||||
+ cmpq %rdx, %rcx
|
||||
+ jb HIDDEN_JUMPTARGET (__chk_fail)
|
||||
+END (MEMCPY_CHK)
|
||||
+#endif
|
||||
+
|
||||
+ENTRY (MEMCPY)
|
||||
+ mov %rdi, %rax
|
||||
+#ifdef USE_AS_MEMPCPY
|
||||
+ add %rdx, %rax
|
||||
+#endif
|
||||
+ lea (%rsi, %rdx), %rcx
|
||||
+ lea (%rdi, %rdx), %r9
|
||||
+ cmp $512, %rdx
|
||||
+ ja L(512bytesormore)
|
||||
+
|
||||
+L(check):
|
||||
+ cmp $16, %rdx
|
||||
+ jbe L(less_16bytes)
|
||||
+ cmp $256, %rdx
|
||||
+ jb L(less_256bytes)
|
||||
+ vmovups (%rsi), %zmm0
|
||||
+ vmovups 0x40(%rsi), %zmm1
|
||||
+ vmovups 0x80(%rsi), %zmm2
|
||||
+ vmovups 0xC0(%rsi), %zmm3
|
||||
+ vmovups -0x100(%rcx), %zmm4
|
||||
+ vmovups -0xC0(%rcx), %zmm5
|
||||
+ vmovups -0x80(%rcx), %zmm6
|
||||
+ vmovups -0x40(%rcx), %zmm7
|
||||
+ vmovups %zmm0, (%rdi)
|
||||
+ vmovups %zmm1, 0x40(%rdi)
|
||||
+ vmovups %zmm2, 0x80(%rdi)
|
||||
+ vmovups %zmm3, 0xC0(%rdi)
|
||||
+ vmovups %zmm4, -0x100(%r9)
|
||||
+ vmovups %zmm5, -0xC0(%r9)
|
||||
+ vmovups %zmm6, -0x80(%r9)
|
||||
+ vmovups %zmm7, -0x40(%r9)
|
||||
+ ret
|
||||
+
|
||||
+L(less_256bytes):
|
||||
+ cmp $128, %dl
|
||||
+ jb L(less_128bytes)
|
||||
+ vmovups (%rsi), %zmm0
|
||||
+ vmovups 0x40(%rsi), %zmm1
|
||||
+ vmovups -0x80(%rcx), %zmm2
|
||||
+ vmovups -0x40(%rcx), %zmm3
|
||||
+ vmovups %zmm0, (%rdi)
|
||||
+ vmovups %zmm1, 0x40(%rdi)
|
||||
+ vmovups %zmm2, -0x80(%r9)
|
||||
+ vmovups %zmm3, -0x40(%r9)
|
||||
+ ret
|
||||
+
|
||||
+L(less_128bytes):
|
||||
+ cmp $64, %dl
|
||||
+ jb L(less_64bytes)
|
||||
+ vmovups (%rsi), %zmm0
|
||||
+ vmovups -0x40(%rcx), %zmm1
|
||||
+ vmovups %zmm0, (%rdi)
|
||||
+ vmovups %zmm1, -0x40(%r9)
|
||||
+ ret
|
||||
+
|
||||
+L(less_64bytes):
|
||||
+ cmp $32, %dl
|
||||
+ jb L(less_32bytes)
|
||||
+ vmovdqu (%rsi), %ymm0
|
||||
+ vmovdqu -0x20(%rcx), %ymm1
|
||||
+ vmovdqu %ymm0, (%rdi)
|
||||
+ vmovdqu %ymm1, -0x20(%r9)
|
||||
+ ret
|
||||
+
|
||||
+L(less_32bytes):
|
||||
+ vmovdqu (%rsi), %xmm0
|
||||
+ vmovdqu -0x10(%rcx), %xmm1
|
||||
+ vmovdqu %xmm0, (%rdi)
|
||||
+ vmovdqu %xmm1, -0x10(%r9)
|
||||
+ ret
|
||||
+
|
||||
+L(less_16bytes):
|
||||
+ cmp $8, %dl
|
||||
+ jb L(less_8bytes)
|
||||
+ movq (%rsi), %rsi
|
||||
+ movq -0x8(%rcx), %rcx
|
||||
+ movq %rsi, (%rdi)
|
||||
+ movq %rcx, -0x8(%r9)
|
||||
+ ret
|
||||
+
|
||||
+L(less_8bytes):
|
||||
+ cmp $4, %dl
|
||||
+ jb L(less_4bytes)
|
||||
+ mov (%rsi), %esi
|
||||
+ mov -0x4(%rcx), %ecx
|
||||
+ mov %esi, (%rdi)
|
||||
+ mov %ecx, -0x4(%r9)
|
||||
+ ret
|
||||
+
|
||||
+L(less_4bytes):
|
||||
+ cmp $2, %dl
|
||||
+ jb L(less_2bytes)
|
||||
+ mov (%rsi), %si
|
||||
+ mov -0x2(%rcx), %cx
|
||||
+ mov %si, (%rdi)
|
||||
+ mov %cx, -0x2(%r9)
|
||||
+ ret
|
||||
+
|
||||
+L(less_2bytes):
|
||||
+ cmp $1, %dl
|
||||
+ jb L(less_1bytes)
|
||||
+ mov (%rsi), %cl
|
||||
+ mov %cl, (%rdi)
|
||||
+L(less_1bytes):
|
||||
+ ret
|
||||
+
|
||||
+L(512bytesormore):
|
||||
+#ifdef SHARED_CACHE_SIZE_HALF
|
||||
+ mov $SHARED_CACHE_SIZE_HALF, %r8
|
||||
+#else
|
||||
+ mov __x86_shared_cache_size_half(%rip), %r8
|
||||
+#endif
|
||||
+ cmp %r8, %rdx
|
||||
+ jae L(preloop_large)
|
||||
+ cmp $1024, %rdx
|
||||
+ ja L(1024bytesormore)
|
||||
+ vmovups (%rsi), %zmm0
|
||||
+ vmovups 0x40(%rsi), %zmm1
|
||||
+ vmovups 0x80(%rsi), %zmm2
|
||||
+ vmovups 0xC0(%rsi), %zmm3
|
||||
+ vmovups 0x100(%rsi), %zmm4
|
||||
+ vmovups 0x140(%rsi), %zmm5
|
||||
+ vmovups 0x180(%rsi), %zmm6
|
||||
+ vmovups 0x1C0(%rsi), %zmm7
|
||||
+ vmovups -0x200(%rcx), %zmm8
|
||||
+ vmovups -0x1C0(%rcx), %zmm9
|
||||
+ vmovups -0x180(%rcx), %zmm10
|
||||
+ vmovups -0x140(%rcx), %zmm11
|
||||
+ vmovups -0x100(%rcx), %zmm12
|
||||
+ vmovups -0xC0(%rcx), %zmm13
|
||||
+ vmovups -0x80(%rcx), %zmm14
|
||||
+ vmovups -0x40(%rcx), %zmm15
|
||||
+ vmovups %zmm0, (%rdi)
|
||||
+ vmovups %zmm1, 0x40(%rdi)
|
||||
+ vmovups %zmm2, 0x80(%rdi)
|
||||
+ vmovups %zmm3, 0xC0(%rdi)
|
||||
+ vmovups %zmm4, 0x100(%rdi)
|
||||
+ vmovups %zmm5, 0x140(%rdi)
|
||||
+ vmovups %zmm6, 0x180(%rdi)
|
||||
+ vmovups %zmm7, 0x1C0(%rdi)
|
||||
+ vmovups %zmm8, -0x200(%r9)
|
||||
+ vmovups %zmm9, -0x1C0(%r9)
|
||||
+ vmovups %zmm10, -0x180(%r9)
|
||||
+ vmovups %zmm11, -0x140(%r9)
|
||||
+ vmovups %zmm12, -0x100(%r9)
|
||||
+ vmovups %zmm13, -0xC0(%r9)
|
||||
+ vmovups %zmm14, -0x80(%r9)
|
||||
+ vmovups %zmm15, -0x40(%r9)
|
||||
+ ret
|
||||
+
|
||||
+#ifndef USE_AS_MEMMOVE
|
||||
+L(1024bytesormore):
|
||||
+ sub $0x200, %r9
|
||||
+
|
||||
+/* Loop with unaligned memory access. */
|
||||
+L(gobble_512bytes_loop):
|
||||
+ vmovups (%rsi), %zmm0
|
||||
+ vmovups 0x40(%rsi), %zmm1
|
||||
+ vmovups 0x80(%rsi), %zmm2
|
||||
+ vmovups 0xC0(%rsi), %zmm3
|
||||
+ vmovups 0x100(%rsi), %zmm4
|
||||
+ vmovups 0x140(%rsi), %zmm5
|
||||
+ vmovups 0x180(%rsi), %zmm6
|
||||
+ vmovups 0x1C0(%rsi), %zmm7
|
||||
+ add $0x200, %rsi
|
||||
+ vmovups %zmm0, (%rdi)
|
||||
+ vmovups %zmm1, 0x40(%rdi)
|
||||
+ vmovups %zmm2, 0x80(%rdi)
|
||||
+ vmovups %zmm3, 0xC0(%rdi)
|
||||
+ vmovups %zmm4, 0x100(%rdi)
|
||||
+ vmovups %zmm5, 0x140(%rdi)
|
||||
+ vmovups %zmm6, 0x180(%rdi)
|
||||
+ vmovups %zmm7, 0x1C0(%rdi)
|
||||
+ add $0x200, %rdi
|
||||
+ cmp %r9, %rdi
|
||||
+ jb L(gobble_512bytes_loop)
|
||||
+ vmovups -0x200(%rcx), %zmm0
|
||||
+ vmovups -0x1C0(%rcx), %zmm1
|
||||
+ vmovups -0x180(%rcx), %zmm2
|
||||
+ vmovups -0x140(%rcx), %zmm3
|
||||
+ vmovups -0x100(%rcx), %zmm4
|
||||
+ vmovups -0xC0(%rcx), %zmm5
|
||||
+ vmovups -0x80(%rcx), %zmm6
|
||||
+ vmovups -0x40(%rcx), %zmm7
|
||||
+ vmovups %zmm0, (%r9)
|
||||
+ vmovups %zmm1, 0x40(%r9)
|
||||
+ vmovups %zmm2, 0x80(%r9)
|
||||
+ vmovups %zmm3, 0xC0(%r9)
|
||||
+ vmovups %zmm4, 0x100(%r9)
|
||||
+ vmovups %zmm5, 0x140(%r9)
|
||||
+ vmovups %zmm6, 0x180(%r9)
|
||||
+ vmovups %zmm7, 0x1C0(%r9)
|
||||
+ ret
|
||||
+
|
||||
+/* Align destination for access with non-temporal stores in the loop. */
|
||||
+L(preloop_large):
|
||||
+ mov %rdi, %r8
|
||||
+ and $-0x80, %rdi
|
||||
+ add $0x80, %rdi
|
||||
+ sub %rdi, %r8
|
||||
+ vmovups (%rsi), %zmm0
|
||||
+ vmovups 0x40(%rsi), %zmm1
|
||||
+ vmovups %zmm0, (%rax)
|
||||
+ vmovups %zmm1, 0x40(%rax)
|
||||
+ sub %r8, %rsi
|
||||
+ sub $0x100, %r9
|
||||
+ prefetcht1 (%rsi)
|
||||
+ prefetcht1 0x40(%rsi)
|
||||
+ prefetcht1 0x80(%rsi)
|
||||
+ prefetcht1 0xC0(%rsi)
|
||||
+L(gobble_256bytes_nt_loop):
|
||||
+ prefetcht1 0x100(%rsi)
|
||||
+ prefetcht1 0x140(%rsi)
|
||||
+ prefetcht1 0x180(%rsi)
|
||||
+ prefetcht1 0x1C0(%rsi)
|
||||
+ vmovups (%rsi), %zmm0
|
||||
+ vmovups 0x40(%rsi), %zmm1
|
||||
+ vmovups 0x80(%rsi), %zmm2
|
||||
+ vmovups 0xC0(%rsi), %zmm3
|
||||
+ add $0x100, %rsi
|
||||
+ vmovntdq %zmm0, (%rdi)
|
||||
+ vmovntdq %zmm1, 0x40(%rdi)
|
||||
+ vmovntdq %zmm2, 0x80(%rdi)
|
||||
+ vmovntdq %zmm3, 0xC0(%rdi)
|
||||
+ add $0x100, %rdi
|
||||
+ cmp %r9, %rdi
|
||||
+ jb L(gobble_256bytes_nt_loop)
|
||||
+ sfence
|
||||
+ vmovups -0x100(%rcx), %zmm0
|
||||
+ vmovups -0xC0(%rcx), %zmm1
|
||||
+ vmovups -0x80(%rcx), %zmm2
|
||||
+ vmovups -0x40(%rcx), %zmm3
|
||||
+ vmovups %zmm0, (%r9)
|
||||
+ vmovups %zmm1, 0x40(%r9)
|
||||
+ vmovups %zmm2, 0x80(%r9)
|
||||
+ vmovups %zmm3, 0xC0(%r9)
|
||||
+ ret
|
||||
+#else
|
||||
+/* Memmove implementation. */
|
||||
+L(1024bytesormore):
|
||||
+ cmp %rsi, %rdi
|
||||
+ ja L(1024bytesormore_bkw)
|
||||
+ prefetcht1 (%rsi)
|
||||
+ prefetcht1 0x40(%rsi)
|
||||
+ prefetcht1 0x80(%rsi)
|
||||
+ prefetcht1 0xC0(%rsi)
|
||||
+
|
||||
+/* Loop with unaligned memory access. */
|
||||
+L(gobble_256bytes_loop):
|
||||
+ vmovups (%rsi), %zmm0
|
||||
+ prefetcht1 0x100(%rsi)
|
||||
+ vmovups 0x40(%rsi), %zmm1
|
||||
+ prefetcht1 0x140(%rsi)
|
||||
+ vmovups 0x80(%rsi), %zmm2
|
||||
+ prefetcht1 0x180(%rsi)
|
||||
+ vmovups 0xC0(%rsi), %zmm3
|
||||
+ prefetcht1 0x1C0(%rsi)
|
||||
+ vmovups %zmm0, (%rdi)
|
||||
+ vmovups %zmm1, 0x40(%rdi)
|
||||
+ vmovups %zmm2, 0x80(%rdi)
|
||||
+ vmovups %zmm3, 0xC0(%rdi)
|
||||
+ sub $256, %rdx
|
||||
+ add $256, %rsi
|
||||
+ add $256, %rdi
|
||||
+ cmp $256, %rdx
|
||||
+ jae L(gobble_256bytes_loop)
|
||||
+ jmp L(check)
|
||||
+
|
||||
+L(1024bytesormore_bkw):
|
||||
+ prefetcht1 -0x100(%rcx)
|
||||
+ prefetcht1 -0xC0(%rcx)
|
||||
+ prefetcht1 -0x80(%rcx)
|
||||
+ prefetcht1 -0x40(%rcx)
|
||||
+
|
||||
+/* Loop with unaligned memory access. */
|
||||
+L(gobble_256bytes_loop_bkw):
|
||||
+ vmovups -0x100(%rcx), %zmm0
|
||||
+ prefetcht1 -0x200(%rcx)
|
||||
+ vmovups -0xC0(%rcx), %zmm1
|
||||
+ prefetcht1 -0x1C0(%rcx)
|
||||
+ vmovups -0x80(%rcx), %zmm2
|
||||
+ prefetcht1 -0x180(%rcx)
|
||||
+ vmovups -0x40(%rcx), %zmm3
|
||||
+ prefetcht1 -0x140(%rcx)
|
||||
+ vmovups %zmm0, -0x100(%r9)
|
||||
+ vmovups %zmm1, -0xC0(%r9)
|
||||
+ vmovups %zmm2, -0x80(%r9)
|
||||
+ vmovups %zmm3, -0x40(%r9)
|
||||
+ sub $256, %rdx
|
||||
+ sub $256, %rcx
|
||||
+ sub $256, %r9
|
||||
+ cmp $256, %rdx
|
||||
+ jae L(gobble_256bytes_loop_bkw)
|
||||
+ jmp L(check)
|
||||
+
|
||||
+L(preloop_large):
|
||||
+ cmp %rsi, %rdi
|
||||
+ ja L(preloop_large_bkw)
|
||||
+ vmovups (%rsi), %zmm4
|
||||
+ vmovups 0x40(%rsi), %zmm5
|
||||
+
|
||||
+/* Align destination for access with non-temporal stores in the loop. */
|
||||
+ mov %rdi, %r8
|
||||
+ and $-0x80, %rdi
|
||||
+ add $0x80, %rdi
|
||||
+ sub %rdi, %r8
|
||||
+ sub %r8, %rsi
|
||||
+ add %r8, %rdx
|
||||
+ prefetcht1 (%rsi)
|
||||
+ prefetcht1 0x40(%rsi)
|
||||
+ prefetcht1 0x80(%rsi)
|
||||
+ prefetcht1 0xC0(%rsi)
|
||||
+L(gobble_256bytes_nt_loop):
|
||||
+ vmovups (%rsi), %zmm0
|
||||
+ prefetcht1 0x100(%rsi)
|
||||
+ vmovups 0x40(%rsi), %zmm1
|
||||
+ prefetcht1 0x140(%rsi)
|
||||
+ vmovups 0x80(%rsi), %zmm2
|
||||
+ prefetcht1 0x180(%rsi)
|
||||
+ vmovups 0xC0(%rsi), %zmm3
|
||||
+ prefetcht1 0x1C0(%rsi)
|
||||
+ vmovntdq %zmm0, (%rdi)
|
||||
+ vmovntdq %zmm1, 0x40(%rdi)
|
||||
+ vmovntdq %zmm2, 0x80(%rdi)
|
||||
+ vmovntdq %zmm3, 0xC0(%rdi)
|
||||
+ sub $256, %rdx
|
||||
+ add $256, %rsi
|
||||
+ add $256, %rdi
|
||||
+ cmp $256, %rdx
|
||||
+ ja L(gobble_256bytes_nt_loop)
|
||||
+ sfence
|
||||
+ vmovups %zmm4, (%rax)
|
||||
+ vmovups %zmm5, 0x40(%rax)
|
||||
+ jmp L(check)
|
||||
+
|
||||
+L(preloop_large_bkw):
|
||||
+ vmovups -0x80(%rcx), %zmm4
|
||||
+ vmovups -0x40(%rcx), %zmm5
|
||||
+
|
||||
+/* Align end of destination for access with non-temporal stores. */
|
||||
+ mov %r9, %r8
|
||||
+ and $-0x80, %r9
|
||||
+ sub %r9, %r8
|
||||
+ sub %r8, %rcx
|
||||
+ sub %r8, %rdx
|
||||
+ add %r9, %r8
|
||||
+ prefetcht1 -0x100(%rcx)
|
||||
+ prefetcht1 -0xC0(%rcx)
|
||||
+ prefetcht1 -0x80(%rcx)
|
||||
+ prefetcht1 -0x40(%rcx)
|
||||
+L(gobble_256bytes_nt_loop_bkw):
|
||||
+ vmovups -0x100(%rcx), %zmm0
|
||||
+ prefetcht1 -0x200(%rcx)
|
||||
+ vmovups -0xC0(%rcx), %zmm1
|
||||
+ prefetcht1 -0x1C0(%rcx)
|
||||
+ vmovups -0x80(%rcx), %zmm2
|
||||
+ prefetcht1 -0x180(%rcx)
|
||||
+ vmovups -0x40(%rcx), %zmm3
|
||||
+ prefetcht1 -0x140(%rcx)
|
||||
+ vmovntdq %zmm0, -0x100(%r9)
|
||||
+ vmovntdq %zmm1, -0xC0(%r9)
|
||||
+ vmovntdq %zmm2, -0x80(%r9)
|
||||
+ vmovntdq %zmm3, -0x40(%r9)
|
||||
+ sub $256, %rdx
|
||||
+ sub $256, %rcx
|
||||
+ sub $256, %r9
|
||||
+ cmp $256, %rdx
|
||||
+ ja L(gobble_256bytes_nt_loop_bkw)
|
||||
+ sfence
|
||||
+ vmovups %zmm4, -0x80(%r8)
|
||||
+ vmovups %zmm5, -0x40(%r8)
|
||||
+ jmp L(check)
|
||||
+#endif
|
||||
+END (MEMCPY)
|
||||
+#endif
|
||||
diff --git a/sysdeps/x86_64/multiarch/memcpy.S b/sysdeps/x86_64/multiarch/memcpy.S
|
||||
index 27fca29..64a1bcd 100644
|
||||
--- a/sysdeps/x86_64/multiarch/memcpy.S
|
||||
+++ b/sysdeps/x86_64/multiarch/memcpy.S
|
||||
@@ -30,19 +30,27 @@
|
||||
ENTRY(__new_memcpy)
|
||||
.type __new_memcpy, @gnu_indirect_function
|
||||
LOAD_RTLD_GLOBAL_RO_RDX
|
||||
- leaq __memcpy_avx_unaligned(%rip), %rax
|
||||
+#ifdef HAVE_AVX512_ASM_SUPPORT
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable)
|
||||
+ jz 1f
|
||||
+ HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
|
||||
+ jz 1f
|
||||
+ leaq __memcpy_avx512_no_vzeroupper(%rip), %rax
|
||||
+ ret
|
||||
+#endif
|
||||
+1: leaq __memcpy_avx_unaligned(%rip), %rax
|
||||
HAS_ARCH_FEATURE (AVX_Fast_Unaligned_Load)
|
||||
- jz 1f
|
||||
+ jz 2f
|
||||
ret
|
||||
-1: leaq __memcpy_sse2(%rip), %rax
|
||||
+2: leaq __memcpy_sse2(%rip), %rax
|
||||
HAS_ARCH_FEATURE (Slow_BSF)
|
||||
- jnz 2f
|
||||
+ jnz 3f
|
||||
leaq __memcpy_sse2_unaligned(%rip), %rax
|
||||
ret
|
||||
-2: HAS_CPU_FEATURE (SSSE3)
|
||||
- jz 3f
|
||||
+3: HAS_CPU_FEATURE (SSSE3)
|
||||
+ jz 4f
|
||||
leaq __memcpy_ssse3(%rip), %rax
|
||||
-3: ret
|
||||
+4: ret
|
||||
END(__new_memcpy)
|
||||
|
||||
# undef ENTRY
|
||||
diff --git a/sysdeps/x86_64/multiarch/memcpy_chk.S b/sysdeps/x86_64/multiarch/memcpy_chk.S
|
||||
index 6476c62..a0d56d4 100644
|
||||
--- a/sysdeps/x86_64/multiarch/memcpy_chk.S
|
||||
+++ b/sysdeps/x86_64/multiarch/memcpy_chk.S
|
||||
@@ -30,7 +30,15 @@
|
||||
ENTRY(__memcpy_chk)
|
||||
.type __memcpy_chk, @gnu_indirect_function
|
||||
LOAD_RTLD_GLOBAL_RO_RDX
|
||||
- leaq __memcpy_chk_sse2(%rip), %rax
|
||||
+#ifdef HAVE_AVX512_ASM_SUPPORT
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable)
|
||||
+ jz 1f
|
||||
+# HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
|
||||
+# jz 1f
|
||||
+ leaq __memcpy_avx512_no_vzeroupper(%rip), %rax
|
||||
+ ret
|
||||
+#endif
|
||||
+1: leaq __memcpy_chk_sse2(%rip), %rax
|
||||
HAS_CPU_FEATURE (SSSE3)
|
||||
jz 2f
|
||||
leaq __memcpy_chk_ssse3(%rip), %rax
|
||||
diff --git a/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
|
||||
new file mode 100644
|
||||
index 0000000..518d1fe
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S
|
||||
@@ -0,0 +1,22 @@
|
||||
+/* memmove optimized with AVX512 for KNL hardware.
|
||||
+ Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#define USE_AS_MEMMOVE
|
||||
+#define MEMCPY __memmove_avx512_no_vzeroupper
|
||||
+#define MEMCPY_CHK __memmove_chk_avx512_no_vzeroupper
|
||||
+#include "memcpy-avx512-no-vzeroupper.S"
|
||||
diff --git a/sysdeps/x86_64/multiarch/memmove.c b/sysdeps/x86_64/multiarch/memmove.c
|
||||
index e844531..8da5640 100644
|
||||
--- a/sysdeps/x86_64/multiarch/memmove.c
|
||||
+++ b/sysdeps/x86_64/multiarch/memmove.c
|
||||
@@ -36,6 +36,9 @@ extern __typeof (__redirect_memmove) __memmove_sse2 attribute_hidden;
|
||||
extern __typeof (__redirect_memmove) __memmove_ssse3 attribute_hidden;
|
||||
extern __typeof (__redirect_memmove) __memmove_ssse3_back attribute_hidden;
|
||||
extern __typeof (__redirect_memmove) __memmove_avx_unaligned attribute_hidden;
|
||||
+# ifdef HAVE_AVX512_ASM_SUPPORT
|
||||
+ extern __typeof (__redirect_memmove) __memmove_avx512_no_vzeroupper attribute_hidden;
|
||||
+# endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,12 +52,18 @@ extern __typeof (__redirect_memmove) __memmove_avx_unaligned attribute_hidden;
|
||||
ifunc symbol properly. */
|
||||
extern __typeof (__redirect_memmove) __libc_memmove;
|
||||
libc_ifunc (__libc_memmove,
|
||||
- HAS_ARCH_FEATURE (AVX_Fast_Unaligned_Load)
|
||||
+#ifdef HAVE_AVX512_ASM_SUPPORT
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable)
|
||||
+ && HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
|
||||
+ ? __memmove_avx512_no_vzeroupper
|
||||
+ :
|
||||
+#endif
|
||||
+ (HAS_ARCH_FEATURE (AVX_Fast_Unaligned_Load)
|
||||
? __memmove_avx_unaligned
|
||||
: (HAS_CPU_FEATURE (SSSE3)
|
||||
? (HAS_ARCH_FEATURE (Fast_Copy_Backward)
|
||||
? __memmove_ssse3_back : __memmove_ssse3)
|
||||
- : __memmove_sse2));
|
||||
+ : __memmove_sse2)));
|
||||
|
||||
strong_alias (__libc_memmove, memmove)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/memmove_chk.c b/sysdeps/x86_64/multiarch/memmove_chk.c
|
||||
index 60ed98f..f64da63 100644
|
||||
--- a/sysdeps/x86_64/multiarch/memmove_chk.c
|
||||
+++ b/sysdeps/x86_64/multiarch/memmove_chk.c
|
||||
@@ -26,10 +26,19 @@ extern __typeof (__memmove_chk) __memmove_chk_sse2 attribute_hidden;
|
||||
extern __typeof (__memmove_chk) __memmove_chk_ssse3 attribute_hidden;
|
||||
extern __typeof (__memmove_chk) __memmove_chk_ssse3_back attribute_hidden;
|
||||
extern __typeof (__memmove_chk) __memmove_chk_avx_unaligned attribute_hidden;
|
||||
+# ifdef HAVE_AVX512_ASM_SUPPORT
|
||||
+ extern __typeof (__memmove_chk) __memmove_chk_avx512_no_vzeroupper attribute_hidden;
|
||||
+# endif
|
||||
|
||||
#include "debug/memmove_chk.c"
|
||||
|
||||
libc_ifunc (__memmove_chk,
|
||||
+#ifdef HAVE_AVX512_ASM_SUPPORT
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable)
|
||||
+ && HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
|
||||
+ ? __memmove_chk_avx512_no_vzeroupper
|
||||
+ :
|
||||
+#endif
|
||||
HAS_ARCH_FEATURE (AVX_Fast_Unaligned_Load) ? __memmove_chk_avx_unaligned :
|
||||
(HAS_CPU_FEATURE (SSSE3)
|
||||
? (HAS_ARCH_FEATURE (Fast_Copy_Backward)
|
||||
diff --git a/sysdeps/x86_64/multiarch/mempcpy-avx512-no-vzeroupper.S b/sysdeps/x86_64/multiarch/mempcpy-avx512-no-vzeroupper.S
|
||||
new file mode 100644
|
||||
index 0000000..ccffb31
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86_64/multiarch/mempcpy-avx512-no-vzeroupper.S
|
||||
@@ -0,0 +1,22 @@
|
||||
+/* mempcpy optimized with AVX512 for KNL hardware.
|
||||
+ Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#define USE_AS_MEMPCPY
|
||||
+#define MEMCPY __mempcpy_avx512_no_vzeroupper
|
||||
+#define MEMCPY_CHK __mempcpy_chk_avx512_no_vzeroupper
|
||||
+#include "memcpy-avx512-no-vzeroupper.S"
|
||||
diff --git a/sysdeps/x86_64/multiarch/mempcpy.S b/sysdeps/x86_64/multiarch/mempcpy.S
|
||||
index 96ffb28..ed78623 100644
|
||||
--- a/sysdeps/x86_64/multiarch/mempcpy.S
|
||||
+++ b/sysdeps/x86_64/multiarch/mempcpy.S
|
||||
@@ -28,7 +28,15 @@
|
||||
ENTRY(__mempcpy)
|
||||
.type __mempcpy, @gnu_indirect_function
|
||||
LOAD_RTLD_GLOBAL_RO_RDX
|
||||
- leaq __mempcpy_sse2(%rip), %rax
|
||||
+#ifdef HAVE_AVX512_ASM_SUPPORT
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable)
|
||||
+ jz 1f
|
||||
+ HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
|
||||
+ jz 1f
|
||||
+ leaq __mempcpy_avx512_no_vzeroupper(%rip), %rax
|
||||
+ ret
|
||||
+#endif
|
||||
+1: leaq __mempcpy_sse2(%rip), %rax
|
||||
HAS_CPU_FEATURE (SSSE3)
|
||||
jz 2f
|
||||
leaq __mempcpy_ssse3(%rip), %rax
|
||||
diff --git a/sysdeps/x86_64/multiarch/mempcpy_chk.S b/sysdeps/x86_64/multiarch/mempcpy_chk.S
|
||||
index ae7a765..6e8a89d 100644
|
||||
--- a/sysdeps/x86_64/multiarch/mempcpy_chk.S
|
||||
+++ b/sysdeps/x86_64/multiarch/mempcpy_chk.S
|
||||
@@ -30,7 +30,15 @@
|
||||
ENTRY(__mempcpy_chk)
|
||||
.type __mempcpy_chk, @gnu_indirect_function
|
||||
LOAD_RTLD_GLOBAL_RO_RDX
|
||||
- leaq __mempcpy_chk_sse2(%rip), %rax
|
||||
+#ifdef HAVE_AVX512_ASM_SUPPORT
|
||||
+ HAS_ARCH_FEATURE (AVX512F_Usable)
|
||||
+ jz 1f
|
||||
+ HAS_ARCH_FEATURE (Prefer_No_VZEROUPPER)
|
||||
+ jz 1f
|
||||
+ leaq __mempcpy_chk_avx512_no_vzeroupper(%rip), %rax
|
||||
+ ret
|
||||
+#endif
|
||||
+1: leaq __mempcpy_chk_sse2(%rip), %rax
|
||||
HAS_CPU_FEATURE (SSSE3)
|
||||
jz 2f
|
||||
leaq __mempcpy_chk_ssse3(%rip), %rax
|
62
nsswitch.conf
Normal file
62
nsswitch.conf
Normal file
@ -0,0 +1,62 @@
|
||||
#
|
||||
# /etc/nsswitch.conf
|
||||
#
|
||||
# An example Name Service Switch config file. This file should be
|
||||
# sorted with the most-used services at the beginning.
|
||||
#
|
||||
# The entry '[NOTFOUND=return]' means that the search for an
|
||||
# entry should stop if the search in the previous entry turned
|
||||
# up nothing. Note that if the search failed due to some other reason
|
||||
# (like no NIS server responding) then the search continues with the
|
||||
# next entry.
|
||||
#
|
||||
# Valid entries include:
|
||||
#
|
||||
# nisplus Use NIS+ (NIS version 3)
|
||||
# nis Use NIS (NIS version 2), also called YP
|
||||
# dns Use DNS (Domain Name Service)
|
||||
# files Use the local files
|
||||
# db Use the local database (.db) files
|
||||
# compat Use NIS on compat mode
|
||||
# hesiod Use Hesiod for user lookups
|
||||
# [NOTFOUND=return] Stop searching if not found so far
|
||||
#
|
||||
|
||||
# To use db, put the "db" in front of "files" for entries you want to be
|
||||
# looked up first in the databases
|
||||
#
|
||||
# Example:
|
||||
#passwd: db files nisplus nis
|
||||
#shadow: db files nisplus nis
|
||||
#group: db files nisplus nis
|
||||
|
||||
passwd: files sss
|
||||
shadow: files sss
|
||||
group: files sss
|
||||
|
||||
#hosts: db files nisplus nis dns
|
||||
hosts: files dns
|
||||
|
||||
# Example - obey only what nisplus tells us...
|
||||
#services: nisplus [NOTFOUND=return] files
|
||||
#networks: nisplus [NOTFOUND=return] files
|
||||
#protocols: nisplus [NOTFOUND=return] files
|
||||
#rpc: nisplus [NOTFOUND=return] files
|
||||
#ethers: nisplus [NOTFOUND=return] files
|
||||
#netmasks: nisplus [NOTFOUND=return] files
|
||||
|
||||
bootparams: nisplus [NOTFOUND=return] files
|
||||
|
||||
ethers: files
|
||||
netmasks: files
|
||||
networks: files
|
||||
protocols: files
|
||||
rpc: files
|
||||
services: files sss
|
||||
|
||||
netgroup: nisplus sss
|
||||
|
||||
publickey: nisplus
|
||||
|
||||
automount: files nisplus
|
||||
aliases: files nisplus
|
@ -3,8 +3,8 @@
|
||||
export QUILT_PATCHES=$PWD
|
||||
# Extract source file name from sources file,
|
||||
# and assume it's the same name as the directory.
|
||||
source=`awk -F '[() ]+' '/^[A-Z0-9]+ /{print $2}; /^[0-9a-f]+ /{print $2}' sources`
|
||||
srcdir=${source%.tar.xz}
|
||||
source=`cat sources | sed -e 's,^.* ,,g'`
|
||||
srcdir=${source%.tar.gz}
|
||||
if [ "$1" == "-f" ] && [ -d "$srcdir" ]; then
|
||||
echo Cleaning up $srcdir
|
||||
rm -rf $srcdir
|
||||
@ -14,7 +14,7 @@ if [ -d "$srcdir" ]; then
|
||||
echo "ERROR: Source directory $srcdir already exists. Use -f to force cleanup step."
|
||||
exit 1
|
||||
fi
|
||||
tar Jxvf $source
|
||||
tar zxvf $source
|
||||
echo "Entering $srcdir"
|
||||
pushd $srcdir
|
||||
# Apply all patches.
|
||||
|
41
series
Normal file
41
series
Normal file
@ -0,0 +1,41 @@
|
||||
glibc-fedora-nscd.patch -p1 --fuzz=0
|
||||
glibc-fedora-ldd.patch -p1 --fuzz=0
|
||||
glibc-fedora-ppc-unwind.patch -p1 --fuzz=0
|
||||
glibc-rh825061.patch -p1 --fuzz=0
|
||||
glibc-arm-hardfloat-3.patch -p1 --fuzz=0
|
||||
glibc-rh697421.patch -p1 --fuzz=0
|
||||
glibc-fedora-include-bits-ldbl.patch -p1 --fuzz=0
|
||||
glibc-fedora-linux-tcsetattr.patch -p1 --fuzz=0
|
||||
glibc-rh741105.patch -p1 --fuzz=0
|
||||
glibc-fedora-nptl-linklibc.patch -p1 --fuzz=0
|
||||
glibc-fedora-localedef.patch -p1 --fuzz=0
|
||||
glibc-fedora-i386-tls-direct-seg-refs.patch -p1 --fuzz=0
|
||||
glibc-fedora-nis-rh188246.patch -p1 --fuzz=0
|
||||
glibc-fedora-manual-dircategory.patch -p1 --fuzz=0
|
||||
glibc-rh827510.patch -p1 --fuzz=0
|
||||
glibc-fedora-locarchive.patch -p1 --fuzz=0
|
||||
glibc-fedora-streams-rh436349.patch -p1 --fuzz=0
|
||||
glibc-rh819430.patch -p1 --fuzz=0
|
||||
glibc-fedora-localedata-rh61908.patch -p1 --fuzz=0
|
||||
glibc-fedora-uname-getrlimit.patch -p1 --fuzz=0
|
||||
glibc-fedora-__libc_multiple_libcs.patch -p1 --fuzz=0
|
||||
glibc-fedora-elf-ORIGIN.patch -p1 --fuzz=0
|
||||
glibc-rh952799.patch -p1 --fuzz=0
|
||||
glibc-rh1009145.patch -p1 --fuzz=0
|
||||
glibc-rh1013801.patch -p1 --fuzz=0
|
||||
glibc-rh1070416.patch -p1 --fuzz=0
|
||||
glibc-nscd-sysconfig.patch -p1 --fuzz=0
|
||||
glibc-aarch64-tls-fixes.patch -p1 --fuzz=0
|
||||
glibc-aarch64-workaround-nzcv-clobber-in-tlsdesc.patch -p1 --fuzz=0
|
||||
glibc-disable-rwlock-elision.patch -p1 --fuzz=0
|
||||
glibc-cs-path.patch -p1 --fuzz=0
|
||||
glibc-bench-build.patch -p1 --fuzz=0
|
||||
glibc-res-hconf-gcc5.patch -p1 --fuzz=0
|
||||
glibc-ld-ctype-gcc5.patch -p1 --fuzz=0
|
||||
glibc-gethnamaddr-gcc5.patch -p1 --fuzz=0
|
||||
glibc-dns-host-gcc5.patch -p1 --fuzz=0
|
||||
glibc-bug-regex-gcc5.patch -p1 --fuzz=0
|
||||
glibc-c-utf8-locale.patch -p1 --fuzz=0
|
||||
glibc-nsswitch-Add-group-merging-support.patch -p1 --fuzz=0
|
||||
glibc-pthread-barrier.patch -p1 --fuzz=0
|
||||
mem-avx512-2016-v4.patch
|
2
sources
2
sources
@ -1 +1 @@
|
||||
SHA512 (glibc-2.30.9000-100-g1a6566094d.tar.xz) = e6054a8f1367fde262f023c76f7eaf5ce588613c4894b8d577c7e1c3159a2dfcefb7c60e301340b823cd8e6d2f8d264d7da83e61034b9180836d392d5db4c5ba
|
||||
f7b4240a89702c8f04967310b8384fec glibc-2.22-621-g90c400b.tar.gz
|
||||
|
97
sync-upstream.sh
Executable file
97
sync-upstream.sh
Executable file
@ -0,0 +1,97 @@
|
||||
#!/bin/sh
|
||||
# Given a git source repo, generate a tarball from the desired branch, modify
|
||||
# the spec file and upload it to lookaside cache if the tarball unpacks and
|
||||
# gets patched cleanly.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# 1. Invoke the script as follows:
|
||||
#
|
||||
# ./sync-upstream.sh upstream-repo
|
||||
#
|
||||
# where upstream-repo is the path to the synced upstream git repo.
|
||||
#
|
||||
# 2. Watch the script run. If it proceeds to building the package, then
|
||||
# everything seems good and you just need to test the build after it
|
||||
# is complete. If it exits before the build (you'll know if you read
|
||||
# the output of the script) then manual intervention is required to
|
||||
# complete the sync. This will typically happen when a patch fails
|
||||
# to apply on the new sources.
|
||||
|
||||
set -e
|
||||
|
||||
# We want to sync from master by default. Change this if you want to sync from
|
||||
# another branch.
|
||||
branch=master
|
||||
|
||||
# We can't do anything without an upstream repo
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: $0 <path-to-upstream-repo>" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
upstream=$1
|
||||
|
||||
srcdir=$(git --git-dir=$upstream/.git describe $branch)
|
||||
cursrc=$(sed -ne 's/^%define glibcsrcdir \(.*\)/\1/p' glibc.spec)
|
||||
|
||||
# Upstream has not moved forward since the last sync.
|
||||
# TODO: Some time in the future, we might want to only sync when upstream has
|
||||
# advanced more than a certain number of commits, say, 42.
|
||||
if [ "$cursrc" = "$srcdir" ]; then
|
||||
echo "+ Already in sync with upstream."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Generate and gzip the tarball from the desired branch of the repository.
|
||||
echo "+ Generating tarball."
|
||||
git --git-dir="$upstream/.git" archive --prefix="$srcdir/" "$branch" \
|
||||
> "$srcdir.tar"
|
||||
gzip -9 "$srcdir.tar"
|
||||
echo "+ Created $srcdir.tar.gz"
|
||||
|
||||
# Our changelog header
|
||||
cldate=$(date +'%a %b %d %Y')
|
||||
clname=$(git config --get user.name)
|
||||
clemail=$(git config --get user.email | sed 's/@/\\@/')
|
||||
|
||||
# Getting our version and release number from the spec file.
|
||||
nv=$(perl -ne 's/^%define glibcversion (.+)/printf("%s-", $1)/e;' \
|
||||
-e 's/^%define glibcrelease ([0-9]+).*/printf("%d\n", $1 + 1)/e;' \
|
||||
glibc.spec)
|
||||
|
||||
# Our changelog entry.
|
||||
changelog="* $cldate $clname <$clemail> - $nv\n- Auto-sync with upstream $branch.\n"
|
||||
|
||||
# Change the glibcsrcdir variable, bump up the release number and add an extra
|
||||
# entry to the changelog.
|
||||
echo "+ Updating spec file."
|
||||
perl -pi \
|
||||
-e "s/^(%define glibcsrcdir ).+/\$1$srcdir/;
|
||||
s/^(%define glibcrelease )(\d+)/print(\$1); print(\$2 + 1);'';/e;
|
||||
s/^(%changelog)$/\$1\n$changelog/" \
|
||||
glibc.spec
|
||||
|
||||
function prep_failed {
|
||||
# fedpkg prep failed.
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "+ Source prep failed."
|
||||
echo "+ Check the output in $tmpfile and fix things before committing."
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
echo "+ Testing if fedpkg prep works."
|
||||
tmpfile=$(mktemp fedpkg-prep.out-XXXX)
|
||||
|
||||
trap prep_failed EXIT
|
||||
fedpkg prep > "$tmpfile" 2>&1
|
||||
# Remove mess created by fedpkg prep
|
||||
rm -f "$tmpfile"
|
||||
rm -rf "$srcdir"
|
||||
echo "+ Source prep is clean, so we're good to go."
|
||||
fedpkg new-sources "$srcdir.tar.gz"
|
||||
git commit -a -m "Auto-sync with upstream $branch."
|
||||
fedpkg push
|
||||
fedpkg build
|
||||
echo "+ Done!"
|
@ -5,7 +5,7 @@ Origin: <Source repo(s) where it came from or keyword "PATCH" if this is simply
|
||||
Bug-RHEL: <Rhel bug #'s, comma separated e.g. #XXX, #YYY, #ZZZ>
|
||||
Bug-Fedora: <Fedora bug #'s, comma separated e.g. #XXX, #YYY, #ZZZ>
|
||||
Bug-Upstream: <Upstream bug#'s, comma separated e.g. #XXX, #YYY, #ZZZ>
|
||||
Upstream status: <[Patchwork URL|libc-alpha URL|not-needed|not-submitted|committed] for each commit>
|
||||
# <Additional descriptive text follows 'Upstream status:' line>
|
||||
Upstream status: <[Patchwork URL|not-needed|not-submitted|committed] for each commit>
|
||||
# <Additional descriptive text in comment block>
|
||||
<If upstream status == committed then a copy of the upstream commit log follows>
|
||||
<Patch>
|
||||
|
Loading…
x
Reference in New Issue
Block a user